aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authoryaworsky <yaworsky>2005-09-16 08:33:41 +0000
committeryaworsky <yaworsky>2005-09-16 08:33:41 +0000
commita2c534419863b2c09fd122d8d1ef6769398f7cf0 (patch)
treec58907db78a04c9d4fae9999651e1a7293cf38f1 /client
parent7875bee3ddfd14f2128540609519306742a78dec (diff)
downloadsyslog-win32-a2c534419863b2c09fd122d8d1ef6769398f7cf0.tar.gz
syslog-win32-a2c534419863b2c09fd122d8d1ef6769398f7cf0.tar.xz
syslog-win32-a2c534419863b2c09fd122d8d1ef6769398f7cf0.zip
Added to repository.
Diffstat (limited to 'client')
-rw-r--r--client/syslog-client.c464
1 files changed, 464 insertions, 0 deletions
diff --git a/client/syslog-client.c b/client/syslog-client.c
new file mode 100644
index 0000000..c9dc86d
--- /dev/null
+++ b/client/syslog-client.c
@@ -0,0 +1,464 @@
+/*
+ * 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.
+ *
+ */
+
+/* define SYSLOG_CONF_DIR where syslog.host should be
+ */
+
+#ifndef SYSLOG_CONF_DIR
+static const char *syslog_conf_dir = ".";
+#else
+static const char *syslog_conf_dir = SYSLOG_CONF_DIR;
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <syslog.h>
+
+#ifdef TEST
+# define SYSLOG_DGRAM_SIZE 80
+#else
+# define SYSLOG_DGRAM_SIZE 1024
+#endif
+
+static BOOL initialized = FALSE;
+static int log_mask = 0xFF;
+static char *syslog_ident;
+static int syslog_facility;
+static char str_pid[ 40 ];
+static SOCKADDR_IN sa_logger;
+static SOCKET sock;
+static char local_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ];
+static char datagramm[ SYSLOG_DGRAM_SIZE ];
+static int datagramm_size;
+
+/******************************************************************************
+ * set_syslog_conf_dir
+ *
+ * maybe this function will be useful...
+ */
+const char* set_syslog_conf_dir( const char* dir )
+{
+ const char *ret = syslog_conf_dir;
+ syslog_conf_dir = dir;
+ return ret;
+}
+
+/******************************************************************************
+ * init_logger_addr
+ *
+ * Read configuration file syslog.host. This file should contain host address
+ * and, optionally, port. Initialize sa_logger. If the configuration file does
+ * not exist, use localhost:514.
+ * Returns: 0 - ok, -1 - error.
+ */
+static void init_logger_addr()
+{
+ char pathname[ FILENAME_MAX ];
+ char *p;
+ FILE *fd;
+ char host[256];
+ struct hostent * phe;
+
+ memset( &sa_logger, 0, sizeof(SOCKADDR_IN) );
+ sa_logger.sin_family = AF_INET;
+
+ if( '\\' == syslog_conf_dir[0] || '/' == syslog_conf_dir[0] || ':' == syslog_conf_dir[1] )
+ {
+ /* absolute path */
+ strcpy( pathname, syslog_conf_dir );
+ }
+ else
+ {
+ /* relative path */
+ char *q;
+
+ strcpy( pathname, __argv[0] );
+ p = strrchr( pathname, '\\' ) + 1;
+ q = strrchr( pathname, '/' ) + 1;
+ if( p < q )
+ *q = 0;
+ else if( p > q )
+ *p = 0;
+ else
+ pathname[0] = 0;
+ strcat( pathname, syslog_conf_dir );
+ }
+ p = &pathname[ strlen( pathname ) - 1 ];
+ if( '\\' != *p && '/' != *p )
+ {
+ p++; *p = '/';
+ }
+ strcpy( ++p, "syslog.host" );
+
+ /* read destination host name */
+ fd = fopen( pathname, "r" );
+ if( !fd )
+ goto use_default;
+
+ if( NULL == fgets( host, sizeof(host), fd ) )
+ host[0] = 0;
+ else
+ {
+ p = strchr( host, '\n' );
+ if( p )
+ *p = 0;
+ p = strchr( host, '\r' );
+ if( p )
+ *p = 0;
+ }
+ fclose( fd );
+
+ p = strchr( host, ':' );
+ if( p )
+ *p++ = 0;
+
+ phe = gethostbyname( host );
+ if( !phe )
+ goto use_default;
+
+ memcpy( &sa_logger.sin_addr.s_addr, phe->h_addr, phe->h_length );
+
+ if( p )
+ sa_logger.sin_port = htons( (unsigned short) strtoul( p, NULL, 0 ) );
+ else
+ sa_logger.sin_port = htons( SYSLOG_PORT );
+ return;
+
+use_default:
+ sa_logger.sin_addr.S_un.S_addr = htonl( 0x7F000001 );
+ sa_logger.sin_port = htons( SYSLOG_PORT );
+}
+
+/******************************************************************************
+ * closelog
+ *
+ * Close desriptor used to write to system logger.
+ */
+void closelog()
+{
+ if( !initialized )
+ return;
+ closesocket( sock );
+ WSACleanup();
+ initialized = FALSE;
+}
+
+/******************************************************************************
+ * openlog
+ *
+ * Open connection to system logger.
+ */
+void openlog( char* ident, int option, int facility )
+{
+ BOOL failed = TRUE, wsa_initialized = FALSE;
+ WSADATA wsd;
+ SOCKADDR_IN sa_local;
+ DWORD n;
+ int size;
+
+ if( initialized )
+ return;
+
+ syslog_facility = facility? facility : LOG_USER;
+
+ /* FIXME: should we reset logmask? */
+
+ if( option & LOG_PID )
+ snprintf( str_pid, sizeof(str_pid), "[%lu]", GetCurrentProcessId() );
+ else
+ str_pid[0] = 0;
+
+ /* FIXME: handle other options */
+
+ n = sizeof(local_hostname);
+ if( !GetComputerName( local_hostname, &n ) )
+ goto done;
+
+ sock = INVALID_SOCKET;
+ if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) )
+ goto done;
+ wsa_initialized = TRUE;
+
+ init_logger_addr();
+
+ for( n = 0;; n++ )
+ {
+ sock = socket( AF_INET, SOCK_DGRAM, 0 );
+ if( INVALID_SOCKET == sock )
+ goto done;
+
+ memset( &sa_local, 0, sizeof(SOCKADDR_IN) );
+ sa_local.sin_family = AF_INET;
+ if( bind( sock, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) == 0 )
+ break;
+ closesocket( sock );
+ sock = INVALID_SOCKET;
+ if( n == 100 )
+ goto done;
+ Sleep(0);
+ }
+
+ /* get size of datagramm */
+ size = sizeof(datagramm_size);
+ if( getsockopt( sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*) &datagramm_size, &size ) )
+ goto done;
+ if( datagramm_size - strlen(local_hostname) - (ident? strlen(ident) : 0) < 64 )
+ goto done;
+ if( datagramm_size > sizeof(datagramm) )
+ datagramm_size = sizeof(datagramm);
+
+ if( atexit( closelog ) )
+ goto done;
+
+ syslog_ident = ident;
+ syslog_facility = facility;
+ failed = FALSE;
+
+done:
+ if( failed )
+ {
+ if( sock != INVALID_SOCKET ) closesocket( sock );
+ if( wsa_initialized ) WSACleanup();
+ }
+ initialized = !failed;
+}
+
+/******************************************************************************
+ * setlogmask
+ *
+ * Set the log mask level.
+ */
+int setlogmask( int mask )
+{
+ int ret = log_mask;
+
+ if( mask )
+ log_mask = mask;
+ return ret;
+}
+
+/******************************************************************************
+ * syslog
+ *
+ * Generate a log message using FMT string and option arguments.
+ */
+void syslog( int pri, char* fmt, ... )
+{
+ va_list ap;
+
+ va_start( ap, fmt );
+ vsyslog( pri, fmt, ap );
+ va_end( ap );
+}
+
+/******************************************************************************
+ * vsyslog
+ *
+ * Generate a log message using FMT and using arguments pointed to by AP.
+ */
+void vsyslog( int pri, char* fmt, va_list ap )
+{
+ static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ SYSTEMTIME stm;
+ int len;
+ char *p;
+
+ if( !(LOG_MASK( LOG_PRI( pri )) & log_mask) )
+ return;
+
+ openlog( NULL, 0, pri & LOG_FACMASK );
+ if( !initialized )
+ return;
+
+ if( !(pri & LOG_FACMASK) )
+ pri |= syslog_facility;
+
+ GetLocalTime( &stm );
+ len = sprintf( datagramm, "<%d>%s %2d %02d:%02d:%02d %s %s%s: ",
+ pri,
+ month[ stm.wMonth - 1 ], stm.wDay, stm.wHour, stm.wMinute, stm.wSecond,
+ local_hostname, syslog_ident? syslog_ident : "", str_pid );
+ vsnprintf( datagramm + len, datagramm_size - len, fmt, ap );
+ p = strchr( datagramm, '\n' );
+ if( p )
+ *p = 0;
+ p = strchr( datagramm, '\r' );
+ if( p )
+ *p = 0;
+
+ sendto( sock, datagramm, strlen(datagramm), 0, (SOCKADDR*) &sa_logger, sizeof(SOCKADDR_IN) );
+}
+
+/******************************************************************************
+ * test
+ */
+#ifdef TEST
+
+static HANDLE hRxEvent = NULL, hAckEvent = NULL;
+static SOCKET rxsock = INVALID_SOCKET;
+static char buffer[ sizeof(datagramm)+1 ];
+
+static DWORD WINAPI listener( LPVOID param )
+{
+ for(;;)
+ {
+ int ret;
+
+ WaitForSingleObject( hAckEvent, INFINITE );
+ ret = recv( rxsock, buffer, sizeof(datagramm), 0 );
+ if( ret <= 0 )
+ break;
+ buffer[ ret ] = 0;
+ SetEvent( hRxEvent );
+ }
+ return 0;
+}
+
+static int transact( int pri, char* fmt, ... )
+{
+ va_list ap;
+ DWORD r;
+
+ va_start( ap, fmt );
+ vsyslog( pri, fmt, ap );
+ va_end( ap );
+ r = WaitForSingleObject( hRxEvent, 2000 );
+ if( WAIT_TIMEOUT == r )
+ {
+ fprintf( stderr, "timeout\n" );
+ return -1;
+ }
+ if( WAIT_FAILED == r )
+ {
+ fprintf( stderr, "wait failed, error %lu\n", GetLastError() );
+ return -1;
+ }
+ printf( "*** %s\n", buffer );
+ SetEvent( hAckEvent );
+ return 0;
+}
+
+int main( int argc, char* argv[] )
+{
+ int ret = 1;
+ WSADATA wsd;
+ SOCKADDR_IN sa_local;
+ DWORD tid;
+ HANDLE hThread = NULL;
+
+ if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) )
+ {
+ fprintf( stderr, "WSAStartup() failed, error %d\n", WSAGetLastError() );
+ return 1;
+ }
+
+ hRxEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if( !hRxEvent )
+ {
+ fprintf( stderr, "CreateEvent() failed, error %lu\n", GetLastError() );
+ goto done;
+ }
+
+ hAckEvent = CreateEvent( NULL, FALSE, TRUE, NULL );
+ if( !hAckEvent )
+ {
+ fprintf( stderr, "CreateEvent() failed, error %lu\n", GetLastError() );
+ goto done;
+ }
+
+ rxsock = socket( AF_INET, SOCK_DGRAM, 0 );
+ if( INVALID_SOCKET == sock )
+ {
+ fprintf( stderr, "socket() failed, error %d\n", WSAGetLastError() );
+ goto done;
+ }
+
+ memset( &sa_local, 0, sizeof(SOCKADDR_IN) );
+ sa_local.sin_family = AF_INET;
+ sa_local.sin_addr.S_un.S_addr = htonl( 0x7F000001 );
+ sa_local.sin_port = htons( SYSLOG_PORT );
+ if( bind( rxsock, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) )
+ {
+ fprintf( stderr, "bind() failed, error %d\n", WSAGetLastError() );
+ goto done;
+ }
+
+ hThread = CreateThread( NULL, 0, listener, NULL, 0, &tid );
+ if( !hThread )
+ {
+ fprintf( stderr, "CreateThread() failed, error %lu\n", GetLastError() );
+ goto done;
+ }
+
+ openlog( "test_ident", 0, LOG_USER );
+ if( !initialized )
+ {
+ fprintf( stderr, "openlog() failed\n" );
+ goto done;
+ }
+
+ if( transact( LOG_DEBUG, "test message %d", 1 ) )
+ goto done;
+
+ setlogmask( LOG_MASK( LOG_EMERG ) );
+
+ if( !transact( LOG_DEBUG, "test message %d", 2 ) )
+ goto done;
+
+ if( transact( LOG_EMERG, "test message %d", 3 ) )
+ goto done;
+
+ closelog();
+ openlog( "test_ident", LOG_PID, LOG_USER );
+ if( !initialized )
+ {
+ fprintf( stderr, "openlog() failed\n" );
+ goto done;
+ }
+
+ setlogmask( LOG_MASK( LOG_DEBUG ) );
+
+ if( transact( LOG_DEBUG, "test message %d with pid", 4 ) )
+ goto done;
+
+ if( transact( LOG_DEBUG, "long test message %d 1234567890 1234567890 1234567890 1234567890 1234567890", 5 ) )
+ goto done;
+
+ ret = 0;
+
+done:
+ if( rxsock != INVALID_SOCKET ) closesocket( rxsock );
+ if( hAckEvent )
+ {
+ if( hThread )
+ {
+ SetEvent( hAckEvent );
+ puts( "waiting for thread shutdown" );
+ WaitForSingleObject( hThread, INFINITE );
+ }
+ CloseHandle( hAckEvent );
+ }
+ if( hThread ) CloseHandle( hThread );
+ if( hRxEvent ) CloseHandle( hRxEvent );
+ WSACleanup();
+ return 0;
+}
+
+#endif /* TEST */