diff options
author | yaworsky <yaworsky> | 2005-11-29 12:13:40 +0000 |
---|---|---|
committer | yaworsky <yaworsky> | 2005-11-29 12:13:40 +0000 |
commit | 2905ea039d3381b6afd6479ff83a5fca33414317 (patch) | |
tree | e06a53184cffc9b0db3d229a38ef3f6c504aadac /daemon | |
parent | c1144cf1e7c0af962487558c1136540eb254f0fe (diff) | |
download | syslog-win32-2905ea039d3381b6afd6479ff83a5fca33414317.tar.gz syslog-win32-2905ea039d3381b6afd6479ff83a5fca33414317.tar.xz syslog-win32-2905ea039d3381b6afd6479ff83a5fca33414317.zip |
Rewritten character conversion: do not fail on invalid characters.
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/syslogd.c | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/daemon/syslogd.c b/daemon/syslogd.c index 165896a..5ff5401 100644 --- a/daemon/syslogd.c +++ b/daemon/syslogd.c @@ -16,6 +16,7 @@ */ #include <ctype.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -190,15 +191,65 @@ static struct string* try_convert_string( struct string* s, GIConv cd ) { struct string *ret; gchar *converted_str; + gchar *inbuf, *outbuf; + gsize inbytes_left, outbytes, outbytes_left; + gsize converted_str_len, converted_str_allocated; - converted_str = g_convert_with_iconv( s->gstr->str, -1, cd, NULL, NULL, NULL ); - if( !converted_str ) + converted_str_allocated = s->gstr->len + /* at least */ 1; + converted_str = g_malloc( converted_str_allocated ); + + inbuf = s->gstr->str; + inbytes_left = s->gstr->len; + outbytes = converted_str_allocated; + outbuf = converted_str; + converted_str_len = 0; + + if( 0 == inbytes_left ) + goto done; + + for(;;) { - TRACE( "conversion error\n" ); - return string_addref( s ); + size_t r; + + outbytes_left = outbytes; + + r = g_iconv( cd, &inbuf, &inbytes_left, &outbuf, &outbytes_left ); + converted_str_len += outbytes - outbytes_left; + outbytes = outbytes_left; + if( r != -1 ) + goto done; + + switch( errno ) + { + 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 */ + converted_str_allocated += outbytes; + converted_str = g_realloc( converted_str, converted_str_allocated ); + outbuf = converted_str + converted_str_len; + break; + + case EILSEQ: + inbuf++; + inbytes_left--; + /* FIXME: skip invalid characters? or replace with some fallback? */ + break; + + case EINVAL: + goto done; + + default: + TRACE( "unknown conversion error %d\n", errno ); + g_free( converted_str ); + return string_addref( s ); + } } +done: - ret = string_new( converted_str ); + ret = string_new_len( converted_str, converted_str_len ); g_free( converted_str ); return ret; } |