From 6cbd5fddd7e5be2746d0ceb017aaedd88717848b Mon Sep 17 00:00:00 2001 From: yaworsky Date: Tue, 29 Nov 2005 13:34:12 +0000 Subject: Convert all parts of logged message to destination encoding. This is required if destination encoding is UCS-2 or UCS-4 for example. Otherwise the logfile will not be uniform. Fixed a bug in charset conversion function: divide by zero when cannot convert the first character and calculating new size for the output buffer. --- daemon/conf.c | 35 ++++++++++++++++++++++++----------- daemon/dest_file.c | 6 +++--- daemon/dest_relay.c | 7 ++++--- daemon/syslogd.c | 53 +++++++++++++++++++++++++++++++++++++++++------------ daemon/syslogd.h | 12 ++++++++---- 5 files changed, 80 insertions(+), 33 deletions(-) diff --git a/daemon/conf.c b/daemon/conf.c index 78f95c2..9be1c18 100644 --- a/daemon/conf.c +++ b/daemon/conf.c @@ -679,11 +679,9 @@ parsed: * create_conversion_descriptors * * helper function for resolve_logpaths; - * creates charset conversion descriptors for message and program name */ static void create_conversion_descriptors( struct logpath* logpath ) { - /* create message charset conversion descriptor */ if( logpath->source->encoding || logpath->destination->encoding ) { char *source_encoding = logpath->source->encoding? @@ -693,8 +691,8 @@ static void create_conversion_descriptors( struct logpath* logpath ) if( strcasecmp( source_encoding, destination_encoding ) != 0 ) { - logpath->message_cd = g_iconv_open( destination_encoding, source_encoding ); - if( logpath->message_cd == (GIConv) -1 ) + logpath->src2dest_cd = g_iconv_open( destination_encoding, source_encoding ); + if( logpath->src2dest_cd == (GIConv) -1 ) { ERR( "Cannot convert messages from %s to %s\n", source_encoding, destination_encoding ); @@ -706,9 +704,23 @@ static void create_conversion_descriptors( struct logpath* logpath ) source_encoding, destination_encoding ); } } + + if( strcasecmp( "ASCII", destination_encoding ) != 0 ) + { + logpath->ascii2dest_cd = g_iconv_open( destination_encoding, source_encoding ); + if( logpath->ascii2dest_cd == (GIConv) -1 ) + { + ERR( "Cannot convert messages from ASCII to %s\n", destination_encoding ); + } + else + { + TRACE( "Log path %s-%s: converting messages from ASCII to %s\n", + logpath->source->name, logpath->destination->name, + destination_encoding ); + } + } } - /* create charset conversion descriptor for program name */ if( logpath->source->encoding ) { const gchar *destination_encoding; @@ -717,15 +729,15 @@ static void create_conversion_descriptors( struct logpath* logpath ) if( strcasecmp( logpath->source->encoding, destination_encoding ) != 0 ) { - logpath->program_cd = g_iconv_open( destination_encoding, logpath->source->encoding ); - if( logpath->program_cd == (GIConv) -1 ) + logpath->src2locale_cd = g_iconv_open( destination_encoding, logpath->source->encoding ); + if( logpath->src2locale_cd == (GIConv) -1 ) { - ERR( "Cannot convert program names from %s to %s\n", + ERR( "Cannot convert locale parts from %s to %s\n", logpath->source->encoding, destination_encoding ); } else { - TRACE( "Log path %s-%s: converting program name from %s to %s\n", + TRACE( "Log path %s-%s: converting locale parts from %s to %s\n", logpath->source->name, logpath->destination->name, logpath->source->encoding, destination_encoding ); } @@ -752,8 +764,9 @@ static void resolve_logpaths() g_free( logpath ); logpath = g_malloc( sizeof(struct logpath) ); - logpath->message_cd = (GIConv) -1; - logpath->program_cd = (GIConv) -1; + logpath->src2dest_cd = (GIConv) -1; + logpath->ascii2dest_cd = (GIConv) -1; + logpath->src2locale_cd = (GIConv) -1; /* find source */ for( item = sources; item; item = item->next ) diff --git a/daemon/dest_file.c b/daemon/dest_file.c index c4d3cfe..d0b9ccd 100644 --- a/daemon/dest_file.c +++ b/daemon/dest_file.c @@ -181,8 +181,8 @@ static void write_message_to_logfile( struct file_writer* writer, struct message if( INVALID_HANDLE_VALUE == writer->fd ) return; 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 ); + len = string_concat( &buffer, (*msg)->timestamp, (*msg)->separator, (*msg)->hostname, + (*msg)->separator, (*msg)->message, (*msg)->end_of_line, NULL ); WriteFile( writer->fd, buffer, len, &written, NULL ); g_free( buffer ); release_message( *msg ); @@ -458,7 +458,7 @@ 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->gstr->str ); break; + case 'H': dest += sprintf( dest, "%s", message->hostname_in_locale->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; diff --git a/daemon/dest_relay.c b/daemon/dest_relay.c index 0ddf675..701c2c3 100755 --- a/daemon/dest_relay.c +++ b/daemon/dest_relay.c @@ -100,10 +100,11 @@ static void put_message_to_relay_dest( struct destination* destination, struct m pri = string_printf( "<%d>", LOG_MAKEPRI( msg->facility, msg->priority ) ); if( destination->u.relay.omit_hostname ) - len = string_concat( &buffer, pri, msg->timestamp, space, msg->message, line_feed, NULL ); + len = string_concat( &buffer, pri, msg->timestamp, msg->separator, + msg->message, msg->end_of_line, NULL ); else - len = string_concat( &buffer, pri, msg->timestamp, space, - msg->hostname, space, msg->message, line_feed, NULL ); + len = string_concat( &buffer, pri, msg->timestamp, msg->separator, msg->hostname, + msg->separator, msg->message, msg->end_of_line, NULL ); string_release( pri ); if( len > 1024 ) diff --git a/daemon/syslogd.c b/daemon/syslogd.c index 5ff5401..6f981f1 100644 --- a/daemon/syslogd.c +++ b/daemon/syslogd.c @@ -83,8 +83,11 @@ struct message* create_message( struct source* source, g_free( ts ); msg->hostname = string_addref( hostname ); + msg->hostname_in_locale = string_addref( hostname ); msg->program = string_addref( program ); msg->message = string_addref( message ); + msg->separator = string_addref( space ); + msg->end_of_line = string_addref( line_feed ); TRACE_LEAVE( "message=%p\n", msg ); return msg; @@ -109,8 +112,11 @@ struct message* duplicate_message( struct message* msg ) new_msg->priority = msg->priority; new_msg->timestamp = string_addref( msg->timestamp ); new_msg->hostname = string_addref( msg->hostname ); + new_msg->hostname_in_locale = string_addref( msg->hostname_in_locale ); new_msg->program = string_addref( msg->program ); new_msg->message = string_addref( msg->message ); + new_msg->separator = string_addref( msg->separator ); + new_msg->end_of_line = string_addref( msg->end_of_line ); TRACE_LEAVE( "new message=%p\n", new_msg ); return new_msg; @@ -143,8 +149,11 @@ void release_message( struct message* msg ) string_release( msg->sender ); string_release( msg->timestamp ); string_release( msg->hostname ); + string_release( msg->hostname_in_locale ); string_release( msg->program ); string_release( msg->message ); + string_release( msg->separator ); + string_release( msg->end_of_line ); g_free( msg ); TRACE_LEAVE( "done\n" ); } @@ -223,10 +232,14 @@ static struct string* try_convert_string( struct string* s, GIConv cd ) { case E2BIG: /* guess the right output length */ - outbytes = inbytes_left * - /* average size of destination char: */ - converted_str_len / (s->gstr->len - inbytes_left) - + 16; /* if the result of above expression too small */ + if( s->gstr->len > inbytes_left ) + outbytes = inbytes_left * + /* average size of destination char: */ + converted_str_len / (s->gstr->len - inbytes_left) + + 16; /* if the result of above expression too small */ + else + /* cannot convert the first character; choose some initial value */ + outbytes = 32; converted_str_allocated += outbytes; converted_str = g_realloc( converted_str, converted_str_allocated ); outbuf = converted_str + converted_str_len; @@ -269,7 +282,7 @@ static void mux_message( struct message* msg ) for( item = logpaths; item; item = item->next ) { struct logpath *logpath = item->data; - gboolean need_message_iconv, need_program_iconv; + gboolean need_dest_iconv, need_locale_iconv; struct message *converted_msg; if( logpath->source != msg->source ) @@ -279,10 +292,10 @@ static void mux_message( struct message* msg ) continue; /* convert encoding if needed */ - need_message_iconv = logpath->message_cd != (GIConv) -1; - need_program_iconv = logpath->program_cd != (GIConv) -1; + need_dest_iconv = (logpath->src2dest_cd != (GIConv) -1) && (logpath->ascii2dest_cd != (GIConv) -1); + need_locale_iconv = logpath->src2locale_cd != (GIConv) -1; - if( (!need_message_iconv) && (!need_program_iconv) ) + if( (!need_dest_iconv) && (!need_locale_iconv) ) { converted_msg = msg; reference_message( msg ); @@ -291,15 +304,31 @@ static void mux_message( struct message* msg ) { converted_msg = duplicate_message( msg ); - if( need_message_iconv ) + if( need_dest_iconv ) { + string_release( converted_msg->timestamp ); + converted_msg->timestamp = try_convert_string( msg->timestamp, logpath->ascii2dest_cd ); + + string_release( converted_msg->hostname ); + converted_msg->hostname = try_convert_string( msg->hostname, logpath->src2dest_cd ); + string_release( converted_msg->message ); - converted_msg->message = try_convert_string( msg->message, logpath->message_cd ); + converted_msg->message = try_convert_string( msg->message, logpath->src2dest_cd ); + + string_release( converted_msg->separator ); + converted_msg->separator = try_convert_string( msg->separator, logpath->ascii2dest_cd ); + + string_release( converted_msg->end_of_line ); + converted_msg->end_of_line = try_convert_string( msg->end_of_line, logpath->ascii2dest_cd ); } - if( need_program_iconv ) + if( need_locale_iconv ) { + string_release( converted_msg->hostname_in_locale ); + converted_msg->hostname_in_locale = try_convert_string( msg->hostname_in_locale, + logpath->src2locale_cd ); + string_release( converted_msg->program ); - converted_msg->program = try_convert_string( msg->program, logpath->program_cd ); + converted_msg->program = try_convert_string( msg->program, logpath->src2locale_cd ); } } diff --git a/daemon/syslogd.h b/daemon/syslogd.h index 7b41db8..b7569bb 100644 --- a/daemon/syslogd.h +++ b/daemon/syslogd.h @@ -96,9 +96,12 @@ struct message int facility; int priority; struct string *timestamp; - struct string *hostname; - struct string *program; + struct string *hostname; /* for logging */ + struct string *hostname_in_locale; /* for filename construction */ + struct string *program; /* in locale, for filename construction */ struct string *message; + struct string *separator; + struct string *end_of_line; }; extern struct message* create_message( struct source* source, @@ -197,8 +200,9 @@ struct logpath struct source *source; struct filter *filter; struct destination *destination; - GIConv message_cd; /* charset conversion descriptor for message */ - GIConv program_cd; /* charset conversion descriptor for program name */ + GIConv src2dest_cd; /* charset conversion descriptor for message */ + GIConv ascii2dest_cd; /* charset conversion descriptor for ascii parts of message */ + GIConv src2locale_cd; /* charset conversion descriptor for those parts that are used for filename construction */ }; extern GList *sources; -- cgit v1.2.3