--- systemd-191.old/src/shared/log.c 2012-09-21 06:07:41.885429447 -0400 +++ systemd-191.new/src/shared/log.c 2012-09-24 07:03:24.430017040 -0400 @@ -649,6 +649,68 @@ int log_oom_internal(const char *file, i return -ENOMEM; } +const char *next_format( + const char *format, + va_list *ap) { + + char lm, *cs, *fc, *format_copy, *format_ptr; + + if ( (fc = strchr(format, '%')) ) { + + format_copy = strndup(fc, LINE_MAX); + + // remove any non-format spec % chars + while ( (fc = strstr(format_copy, "%%")) ) + *(fc+1) = *fc = ' '; + + cs = strtok_r(format_copy, "%", &format_ptr); + // no need to worry about 'h' or 'hh' length modifiers as these will promoted to ints + do { + lm = 0; + + while (*cs) { + switch(*cs++) { + case 'l': + lm = (lm == 'l') ? 'L' : 'l'; + break; + case 'L': + lm = 'l'; + break; + case 's': + va_arg(*ap, char *); + *cs = 0; + break; + case 'u': case 'd': case 'i': case 'x': case 'X': case 'c': case 'o': + if (!lm) + va_arg(*ap, int); + else if (lm == 'l') + va_arg(*ap, long); + else if (lm == 'L') + va_arg(*ap, long long); + else + va_arg(*ap, int); + *cs = 0; + break; + case 'e': case 'f': case 'g': case 'E': case 'F': case 'G': + if (lm != 'l') + va_arg(*ap, double); + else + va_arg(*ap, long double); + *cs = 0; + break; + case 'p': + va_arg(*ap, void *); + *cs = 0; + break; + } + } + } while( (cs = strtok_r(NULL, "%", &format_ptr)) ); + + free(format_copy); + } + return va_arg(*ap, char *); +} + int log_struct_internal( int level, const char *file, @@ -657,7 +719,7 @@ int log_struct_internal( const char *format, ...) { int saved_errno; - va_list ap; + va_list ap, app; int r; if (_likely_(LOG_PRI(level) > log_max_level)) @@ -706,7 +768,9 @@ int log_struct_internal( while (format && n + 1 < ELEMENTSOF(iovec)) { char *buf; - if (vasprintf(&buf, format, ap) < 0) { + va_copy(app, ap); + + if (vasprintf(&buf, format, app) < 0) { r = -ENOMEM; goto finish; } @@ -717,7 +781,7 @@ int log_struct_internal( iovec[n].iov_len = 1; n++; - format = va_arg(ap, char *); + format = next_format(format, &ap); } zero(mh); @@ -743,7 +807,9 @@ int log_struct_internal( va_start(ap, format); while (format) { - vsnprintf(buf, sizeof(buf), format, ap); + va_copy(app, ap); + + vsnprintf(buf, sizeof(buf), format, app); char_array_0(buf); if (startswith(buf, "MESSAGE=")) { @@ -751,7 +817,7 @@ int log_struct_internal( break; } - format = va_arg(ap, char *); + format = next_format(format, &ap); } va_end(ap);