From a704fc5981f7f2c0a3179f62f0ce818f75467078 Mon Sep 17 00:00:00 2001 From: yaworsky Date: Tue, 15 Nov 2005 11:59:52 +0000 Subject: Replaced 0-terminated strings with reference counted ones --- daemon/Makefile.am | 4 +- daemon/dest_file.c | 26 +++++++---- daemon/dest_relay.c | 12 ++--- daemon/main.c | 18 +++++-- daemon/string.c | 116 +++++++++++++++++++++++++++++++++++++++++++++ daemon/syslogd.c | 132 ++++++++++++++++++++++++++++------------------------ daemon/syslogd.h | 40 ++++++++++++---- 7 files changed, 255 insertions(+), 93 deletions(-) create mode 100755 daemon/string.c (limited to 'daemon') diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 5e2a426..bda0ed4 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -14,8 +14,8 @@ AM_CPPFLAGS += -I. -I../include $(GLIB_CFLAGS) bin_PROGRAMS = syslogd syslogd_SOURCES = conf.c dest_file.c dest_relay.c fifo.c logrotate.c \ - main.c names.c pathnames.c purger.c syslogd.c syslogd.h \ - udp_listener.c + main.c names.c pathnames.c purger.c string.c syslogd.c \ + syslogd.h udp_listener.c syslogd_LDADD = -lws2_32 $(GLIB_LIBS) endif diff --git a/daemon/dest_file.c b/daemon/dest_file.c index ef28062..f08cedb 100644 --- a/daemon/dest_file.c +++ b/daemon/dest_file.c @@ -67,8 +67,10 @@ static gboolean compare_current_and_first_messages( struct file_writer* writer ) { TRACE_ENTER( "%p\n", writer ); - if( strcmp( writer->current_msg->hostname, writer->first_msg->hostname ) - || strcmp( writer->current_msg->message, writer->first_msg->message ) ) + if( string_compare( writer->current_msg->hostname, + writer->first_msg->hostname ) + || string_compare( writer->current_msg->message, + writer->first_msg->message ) ) { release_message( writer->first_msg ); writer->first_msg = NULL; @@ -173,13 +175,15 @@ check_hold_time: static void write_message_to_logfile( struct file_writer* writer, struct message** msg ) { gchar *buffer; + gsize len; DWORD written; if( INVALID_HANDLE_VALUE == writer->fd ) return; - TRACE_2( "%p: %s\n", writer, (*msg)->message ); - buffer = g_strconcat( (*msg)->timestamp, " ", (*msg)->hostname, " ", (*msg)->message, "\n", NULL ); - WriteFile( writer->fd, buffer, strlen( buffer ), &written, NULL ); + TRACE_2( "%p: %s\n", writer, (*msg)->message->gstr->str ); + len = string_concat( &buffer, (*msg)->timestamp, space, (*msg)->hostname, + space, (*msg)->message, line_feed, NULL ); + WriteFile( writer->fd, buffer, len, &written, NULL ); g_free( buffer ); release_message( *msg ); *msg = NULL; @@ -209,7 +213,7 @@ static void flush_coalescer( struct file_writer* writer ) size = snprintf( buffer, sizeof(buffer), "%s %2d %02d:%02d:%02d %s syslog: last message repeated %d times\n", str_month[ stm.wMonth - 1 ], stm.wDay, stm.wHour, stm.wMinute, stm.wSecond, - local_hostname, + local_hostname->gstr->str, writer->coalesce_count - 1 ); WriteFile( writer->fd, buffer, size, &written, NULL ); TRACE_2( "%p made informational message\n", writer ); @@ -463,9 +467,9 @@ static void make_file_name( char* pattern, struct message* message, char* buffer case 'f': dest += sprintf( dest, "%d", message->facility ); break; case 'L': dest += sprintf( dest, "%s", get_priority_name( message->priority ) ); break; case 'l': dest += sprintf( dest, "%d", message->priority ); break; - case 'H': dest += sprintf( dest, "%s", message->hostname ); break; - case 'h': dest += sprintf( dest, "%s", message->sender ); break; - case 'P': dest += sprintf( dest, "%s", message->program ); break; + case 'H': dest += sprintf( dest, "%s", message->hostname->gstr->str ); break; + case 'h': dest += sprintf( dest, "%s", message->sender->gstr->str ); break; + case 'P': dest += sprintf( dest, "%s", message->program->gstr->str ); break; default: *dest++ = c; break; } } @@ -485,7 +489,9 @@ static void put_message_to_file_dest( struct destination* destination, struct me TRACE_ENTER( "msg=%p, destination=%s\n", msg, destination->name ); make_file_name( destination->u.file.name_pattern, msg, file_name ); EnterCriticalSection( &extra->cs_file_writers ); - /* find existing writer */ + /* find existing writer + FIXME: could we do this better? + */ for( writer = NULL, item = extra->file_writers; item; item = item->next ) { struct file_writer *w = item->data; diff --git a/daemon/dest_relay.c b/daemon/dest_relay.c index 4bea0c6..0ddf675 100755 --- a/daemon/dest_relay.c +++ b/daemon/dest_relay.c @@ -92,20 +92,20 @@ done: static void put_message_to_relay_dest( struct destination* destination, struct message* msg ) { struct dest_extra *extra = destination->extra; - char pri[16]; + struct string *pri; gchar *buffer; int len; TRACE_ENTER( "msg=%p, destination=%s\n", msg, destination->name ); - sprintf( pri, "<%d>", LOG_MAKEPRI( msg->facility, msg->priority ) ); + pri = string_printf( "<%d>", LOG_MAKEPRI( msg->facility, msg->priority ) ); if( destination->u.relay.omit_hostname ) - buffer = g_strconcat( pri, msg->timestamp, " ", msg->message, "\n", NULL ); + len = string_concat( &buffer, pri, msg->timestamp, space, msg->message, line_feed, NULL ); else - buffer = g_strconcat( pri, msg->timestamp, " ", - msg->hostname, " ", msg->message, "\n", NULL ); + len = string_concat( &buffer, pri, msg->timestamp, space, + msg->hostname, space, msg->message, line_feed, NULL ); + string_release( pri ); - len = strlen( buffer ); if( len > 1024 ) { buffer[ 1023 ] = '\n'; diff --git a/daemon/main.c b/daemon/main.c index 91e9087..ee91238 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -28,7 +28,10 @@ HANDLE service_stop_event; -char local_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ]; +struct string *local_hostname; +struct string *self_program_name; +struct string *space; +struct string *line_feed; int verbosity_level = 0; @@ -468,10 +471,15 @@ int main( int argc, char* argv[] ) char *priority = NULL; int getopt_failure = 0; WSADATA wsd; + char name_buf[ MAX_COMPUTERNAME_LENGTH + 1 ]; DWORD size; SetUnhandledExceptionFilter( exception_handler ); + self_program_name = string_new( "syslog" ); + space = string_new( " " ); + line_feed = string_new( "\n" ); + if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) ) { ERR( "Cannot initialize winsock; error %lu\n", WSAGetLastError() ); @@ -479,13 +487,13 @@ int main( int argc, char* argv[] ) } /* get local host name */ - size = sizeof(local_hostname); - if( !GetComputerName( local_hostname, &size ) ) + size = sizeof(name_buf); + if( !GetComputerName( name_buf, &size ) ) { ERR( "Cannot get computer name; error %lu\n", GetLastError() ); return 1; } - TRACE( "local host name=%s\n", local_hostname ); + local_hostname = string_new_len( name_buf, size ); /* get windows version */ vi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); @@ -581,6 +589,8 @@ int main( int argc, char* argv[] ) if( getopt_failure ) return 1; + TRACE( "local host name=%s\n", local_hostname->gstr->str ); + /* handle flags in order of priority */ /* at first, check instance name */ if( instance_name ) diff --git a/daemon/string.c b/daemon/string.c new file mode 100755 index 0000000..6684664 --- /dev/null +++ b/daemon/string.c @@ -0,0 +1,116 @@ +/* + * string.c - syslogd implementation for windows, reference counted strings + * + * 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. + * + */ + +#include +#include +#include + +#include +#include + +#include +#include + +struct string* string_new( const gchar* init ) +{ + struct string *s = g_malloc( sizeof(struct string) ); + s->refcount = 1; + s->gstr = g_string_new( init ); + return s; +} + +struct string* string_new_len( const gchar* init, gssize len ) +{ + struct string *s = g_malloc( sizeof(struct string) ); + s->refcount = 1; + s->gstr = g_string_new_len( init, len ); + return s; +} + +struct string* string_addref( struct string* s ) +{ + InterlockedIncrement( &s->refcount ); + return s; +} + +void string_release( struct string* s ) +{ + if( InterlockedDecrement( &s->refcount ) ) + return; + + g_string_free( s->gstr, TRUE ); + g_free( s ); +} + +gsize string_concat( gchar** result, struct string* s, ... ) +{ + va_list args; + struct string *str; + gsize length = s->gstr->len; + gchar *p; + + va_start( args, s ); + while( (str = va_arg( args, struct string* )) ) + length += str->gstr->len; + va_end( args ); + + *result = g_malloc( length + 1 ); + + memcpy( *result, s->gstr->str, s->gstr->len ); + p = *result + s->gstr->len; + + va_start( args, s ); + while( (str = va_arg( args, struct string* )) ) + { + memcpy( p, str->gstr->str, str->gstr->len ); + p += str->gstr->len; + } + *p = 0; + va_end( args ); + + return length; +} + +struct string* string_vprintf( gchar* fmt, va_list args ) +{ + struct string *s; + gchar *buf; + int len; + + len = g_vasprintf( &buf, fmt, args ); + s = string_new_len( buf, len ); + g_free( buf ); + return s; +} + +struct string* string_printf( gchar* fmt, ... ) +{ + struct string *s; + va_list args; + + va_start( args, fmt ); + s = string_vprintf( fmt, args ); + va_end( args ); + return s; +} + +int string_compare( struct string* s1, struct string* s2 ) +{ + if( s1 == s2 ) + return 0; + return strcmp( s1->gstr->str, s2->gstr->str ); +} diff --git a/daemon/syslogd.c b/daemon/syslogd.c index dc947b3..da53e60 100644 --- a/daemon/syslogd.c +++ b/daemon/syslogd.c @@ -38,7 +38,7 @@ static struct source** internal_source_references = NULL; struct hostname { struct sockaddr_in addr; - gchar *host; + struct string *host; time_t top_age; /* zero prevents aging */ }; static GList *hostnames = NULL; @@ -55,35 +55,37 @@ char *str_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", * create_message * * Create a new message with refcount=1. - * The caller should allocate sender, hostname, program and message strings. - * The function simply copies these pointers to the structure and the caller - * should not free allocated strings. */ struct message* create_message( struct source* source, - gchar* sender, + struct string* sender, int facility, int priority, LPSYSTEMTIME timestamp, - gchar* hostname, - gchar* program, - gchar* message ) + struct string* hostname, + struct string* program, + struct string* message ) { struct message *msg; + gchar *ts; TRACE_ENTER( "\n" ); msg = g_malloc( sizeof(struct message) ); msg->refcount = 1; msg->source = source; - msg->sender = sender; + msg->sender = string_addref( sender ); msg->facility = facility; msg->priority = priority; - msg->timestamp = g_strdup_printf( "%s %2d %02d:%02d:%02d", - str_month[ timestamp->wMonth - 1 ], - timestamp->wDay, timestamp->wHour, - timestamp->wMinute, timestamp->wSecond ); - msg->hostname = hostname; - msg->program = program; - msg->message = message; + + ts = g_strdup_printf( "%s %2d %02d:%02d:%02d", + str_month[ timestamp->wMonth - 1 ], + timestamp->wDay, timestamp->wHour, + timestamp->wMinute, timestamp->wSecond ); + msg->timestamp = string_new( ts ); + g_free( ts ); + + msg->hostname = string_addref( hostname ); + msg->program = string_addref( program ); + msg->message = string_addref( message ); TRACE_LEAVE( "message=%p\n", msg ); return msg; @@ -101,15 +103,15 @@ struct message* duplicate_message( struct message* msg ) TRACE_ENTER( "message=%p\n", msg ); new_msg = g_malloc( sizeof(struct message) ); - new_msg->refcount = 1; - new_msg->source = msg->source; - new_msg->sender = g_strdup( msg->sender ); - new_msg->facility = msg->facility; - new_msg->priority = msg->priority; - new_msg->timestamp = g_strdup( msg->timestamp ); - new_msg->hostname = g_strdup( msg->hostname ); - new_msg->program = g_strdup( msg->program ); - new_msg->message = g_strdup( msg->message ); + new_msg->refcount = 1; + new_msg->source = msg->source; + new_msg->sender = string_addref( msg->sender ); + new_msg->facility = msg->facility; + new_msg->priority = msg->priority; + new_msg->timestamp = string_addref( msg->timestamp ); + new_msg->hostname = string_addref( msg->hostname ); + new_msg->program = string_addref( msg->program ); + new_msg->message = string_addref( msg->message ); TRACE_LEAVE( "new message=%p\n", new_msg ); return new_msg; @@ -139,11 +141,11 @@ void release_message( struct message* msg ) TRACE_LEAVE( "done; still referenced\n" ); return; } - g_free( msg->sender ); - g_free( msg->timestamp ); - g_free( msg->hostname ); - g_free( msg->program ); - g_free( msg->message ); + string_release( msg->sender ); + string_release( msg->timestamp ); + string_release( msg->hostname ); + string_release( msg->program ); + string_release( msg->message ); g_free( msg ); TRACE_LEAVE( "done\n" ); } @@ -163,7 +165,7 @@ static void convert_message_encoding( struct message* msg ) return; } - converted_msg = g_convert_with_iconv( msg->message, -1, + converted_msg = g_convert_with_iconv( msg->message->gstr->str, -1, conversion_descriptor, NULL, NULL, NULL ); if( !converted_msg ) { @@ -171,10 +173,11 @@ static void convert_message_encoding( struct message* msg ) return; } - g_free( msg->message ); - msg->message = converted_msg; + string_release( msg->message ); + msg->message = string_new( converted_msg ); + g_free( converted_msg ); - TRACE_LEAVE( "done; %s\n", msg->message ); + TRACE_LEAVE( "done; %s\n", msg->message->gstr->str ); } /****************************************************************************** @@ -243,14 +246,16 @@ static void mux_message( struct message* msg ) /****************************************************************************** * get_hostname * - * convert addr to string and return it + * convert addr to string and return it; + * string should be released after use */ -static gchar* get_hostname( struct sockaddr_in* addr ) +static struct string* get_hostname( struct sockaddr_in* addr ) { - gchar *ret; + struct string *ret; time_t current_time; GList *item; struct hostname *new_hostname; + char buf[16]; TRACE_ENTER( "%d.%d.%d.%d\n", addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2, @@ -268,7 +273,7 @@ static gchar* get_hostname( struct sockaddr_in* addr ) GList *next_item = item->next; TRACE_2( "delete old entry %s\n", h->host ); - g_free( h->host ); + string_release( h->host ); g_free( h ); hostnames = g_list_delete_link( hostnames, item ); item = next_item; @@ -277,7 +282,7 @@ static gchar* get_hostname( struct sockaddr_in* addr ) if( h->addr.sin_addr.S_un.S_addr == addr->sin_addr.S_un.S_addr ) { /* found in cache */ - ret = g_strdup( h->host ); + ret = string_addref( h->host ); /* move entry to the beginning of the list */ item->data = hostnames->data; hostnames->data = h; @@ -296,19 +301,19 @@ static gchar* get_hostname( struct sockaddr_in* addr ) new_hostname->top_age = time(NULL) + HOSTNAME_LIFETIME; if( !he ) goto use_addr; - new_hostname->host = g_strdup( he->h_name ); + new_hostname->host = string_new( he->h_name ); } else { new_hostname->top_age = 0; use_addr: - new_hostname->host = g_malloc( 16 ); - sprintf( new_hostname->host, "%d.%d.%d.%d", + sprintf( buf, "%d.%d.%d.%d", addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2, addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4 ); + new_hostname->host = string_new( buf ); } hostnames = g_list_prepend( hostnames, new_hostname ); - ret = g_strdup( new_hostname->host ); + ret = string_addref( new_hostname->host ); TRACE_LEAVE( "done; ret=%s\n", ret ); return ret; } @@ -322,7 +327,7 @@ static void free_hostnames() for( item = hostnames; item; item = item->next ) { struct hostname *h = item->data; - g_free( h->host ); + string_release( h->host ); g_free( h ); } g_list_free( hostnames ); @@ -455,7 +460,7 @@ done: static struct message* parse_raw_message( struct raw_message* raw_msg ) { gchar *current_part, *next_part; - gchar *sender, *hostname, *program, *message; + struct string *sender, *hostname, *program, *message; int facility, priority; SYSTEMTIME timestamp; struct message *msg; @@ -474,8 +479,8 @@ static struct message* parse_raw_message( struct raw_message* raw_msg ) { /* no valid timestamp */ TRACE_2( "no valid timestamp: msg=%s\n", current_part ); - hostname = g_strdup( sender ); - message = g_strdup( current_part ); + hostname = string_addref( sender ); + message = string_new( current_part ); } else { @@ -486,33 +491,38 @@ static struct message* parse_raw_message( struct raw_message* raw_msg ) if( *next_part != ' ' ) { /* invalid hostname */ - hostname = g_strdup( sender ); - message = g_strdup( current_part ); - TRACE_2( "invalid hostname; set sender (%s); msg=%s\n", hostname, message ); + hostname = string_addref( sender ); + message = string_new( current_part ); + TRACE_2( "invalid hostname; set sender (%s); msg=%s\n", + hostname->gstr->str, message->gstr->str ); } else { - hostname = g_strndup( current_part, next_part - current_part ); + hostname = string_new_len( current_part, next_part - current_part ); while( *next_part == ' ' && *next_part != 0 ) next_part++; - message = g_strdup( next_part ); - TRACE_2( "hostname=%s; msg=%s\n", hostname, message ); + message = string_new( next_part ); + TRACE_2( "hostname=%s; msg=%s\n", hostname->gstr->str, message->gstr->str ); } } /* try to find program name */ - current_part = message; + current_part = message->gstr->str; next_part = current_part; while( *next_part != ' ' && *next_part != ':' && *next_part != '[' && *next_part != 0 ) next_part++; if( *next_part == ' ' || *next_part == 0 ) - program = g_strdup(""); + program = string_new(""); else - program = g_strndup( current_part, next_part - current_part ); + program = string_new_len( current_part, next_part - current_part ); /* create message */ msg = create_message( raw_msg->source, sender, facility, priority, ×tamp, hostname, program, message ); + string_release( sender ); + string_release( hostname ); + string_release( program ); + string_release( message ); /* destroy raw message */ g_free( raw_msg->msg ); @@ -551,7 +561,7 @@ unsigned number_of_sources( enum source_type type ) */ void log_internal( int pri, char* fmt, ... ) { - gchar *sender, *hostname, *program, *msg; + struct string *sender, *hostname, *program, *msg; va_list args; SYSTEMTIME stm; int i; @@ -562,12 +572,12 @@ void log_internal( int pri, char* fmt, ... ) if( 0 == internal_source_count ) goto done; - sender = g_strdup( local_hostname ); - hostname = g_strdup( local_hostname ); - program = g_strdup( "syslog" ); + sender = string_addref( local_hostname ); + hostname = string_addref( local_hostname ); + program = string_addref( self_program_name ); va_start( args, fmt ); - msg = g_strdup_vprintf( fmt, args ); + msg = string_vprintf( fmt, args ); va_end( args ); GetLocalTime( &stm ); diff --git a/daemon/syslogd.h b/daemon/syslogd.h index 0bcd1fb..c48f8f8 100644 --- a/daemon/syslogd.h +++ b/daemon/syslogd.h @@ -34,9 +34,29 @@ extern void display_message( FILE* fd, char* file, int line, const char* func, c #define TRACE_LEAVE TRACE_2 #define ERR( fmt... ) display_message( stderr, __FILE__, __LINE__, __FUNCTION__, fmt ) +/* refcounted string */ +struct string +{ + LONG refcount; + GString *gstr; +}; + +extern struct string* string_new( const gchar* init ); +extern struct string* string_new_len( const gchar* init, gssize len ); +extern struct string* string_addref( struct string* s ); +extern void string_release( struct string* s ); +extern struct string* string_vprintf( gchar* fmt, va_list args ); +extern struct string* string_printf( gchar* fmt, ... ); +extern gsize string_concat( gchar** result, struct string* s, ... ); +extern int string_compare( struct string* s1, struct string* s2 ); + +/* misc global stuff */ extern HANDLE service_stop_event; -extern char local_hostname[]; +extern struct string *local_hostname; +extern struct string *self_program_name; +extern struct string *space; +extern struct string *line_feed; extern char *str_month[]; @@ -74,22 +94,22 @@ struct message { LONG refcount; struct source *source; - gchar *sender; + struct string *sender; int facility; int priority; - gchar *timestamp; - gchar *hostname; - gchar *program; - gchar *message; + struct string *timestamp; + struct string *hostname; + struct string *program; + struct string *message; }; extern struct message* create_message( struct source* source, - gchar* sender, + struct string* sender, int facility, int priority, LPSYSTEMTIME timestamp, - gchar* hostname, - gchar* program, - gchar* message ); + struct string* hostname, + struct string* program, + struct string* message ); extern struct message* duplicate_message( struct message* msg ); extern void reference_message( struct message* msg ); extern void release_message( struct message* msg ); -- cgit v1.2.3