From b34b3e2817950c6cccbc9cf2fce8cc137f433a88 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 18 May 2012 03:08:40 +0200 Subject: New logging facilities --- src/printf.c | 259 ++++++++++++++++++++--------------------------------------- 1 file changed, 87 insertions(+), 172 deletions(-) (limited to 'src/printf.c') diff --git a/src/printf.c b/src/printf.c index cbecbc8..bf2bc35 100644 --- a/src/printf.c +++ b/src/printf.c @@ -28,207 +28,122 @@ #include "peer.h" #include -#include -static void print_peer_address(const fastd_context *ctx, const fastd_peer_address *address) { +static inline int snprintf_safe(char *buffer, size_t size, const char *format, ...) { + va_list ap; + va_start(ap, format); + int ret = vsnprintf(buffer, size, format, ap); + va_end(ap); + + return ret < 0 ? 0 : ret > size ? size : ret; +} + +static int snprint_peer_address(const fastd_context *ctx, char *buffer, size_t size, const fastd_peer_address *address) { char addr_buf[INET6_ADDRSTRLEN] = ""; switch (address->sa.sa_family) { case AF_UNSPEC: - fputs("floating", stderr); - return; + return snprintf(buffer, size, "floating"); case AF_INET: if (inet_ntop(AF_INET, &address->in.sin_addr, addr_buf, sizeof(addr_buf))) - fprintf(stderr, "%s:%u", addr_buf, ntohs(address->in.sin_port)); - return; + return snprintf_safe(buffer, size, "%s:%u", addr_buf, ntohs(address->in.sin_port)); + else + return 0; case AF_INET6: if (inet_ntop(AF_INET6, &address->in6.sin6_addr, addr_buf, sizeof(addr_buf))) - fprintf(stderr, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port)); - break; + return snprintf_safe(buffer, size, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port)); + else + return 0; default: exit_bug(ctx, "unsupported address family"); } } -static void print_peer_str(const fastd_context *ctx, const fastd_peer *peer) { - if (peer->config && peer->config->name) { - fprintf(stderr, "<%s>", peer->config->name); - } - else { - fputs("<(null)>", stderr); - } +static int snprint_peer_str(const fastd_context *ctx, char *buffer, size_t size, const fastd_peer *peer) { + if (peer->config && peer->config->name) + return snprintf_safe(buffer, size, "<%s>", peer->config->name); + else + return snprintf_safe(buffer, size, "<(null)>"); } -#pragma GCC diagnostic ignored "-Wformat-security" +int fastd_vsnprintf(const fastd_context *ctx, char *buffer, size_t size, const char *format, va_list ap) { + char *buffer_start = buffer; + char *buffer_end = buffer+size; -void fastd_printf(const fastd_context *ctx, const char *format, ...) { - va_list ap; - va_start(ap, format); + *buffer = 0; - char *format_dup = strdup(format); - char *str; - for (str = format_dup; *str; str++) { - if (*str != '%') { - fputc(*str, stderr); + for (; *format; format++) { + const void *p; + const fastd_eth_addr *eth_addr; + + if (buffer >= buffer_end) + break; + + if (*format != '%') { + *buffer = *format; + buffer++; continue; } - int len, flag_l = 0, flag_L = 0, flag_j = 0, flag_z = 0, flag_t = 0; - - for(len = 1; str[len]; len++) { - char last; - bool finished = true; - const void *p; - const fastd_eth_addr *eth_addr; - - switch (str[len]) { - case 'l': - flag_l++; - finished = false; - break; - - case 'L': - flag_L++; - finished = false; - break; - - case 'j': - flag_j++; - finished = false; - break; - - case 'z': - flag_z++; - finished = false; - break; - - case 't': - flag_t++; - finished = false; - break; - - case '%': - fputc('%', stderr); - break; - - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - last = str[len+1]; - str[len+1] = 0; - - if (flag_j) - fprintf(stderr, str, va_arg(ap, intmax_t)); - else if (flag_z) - fprintf(stderr, str, va_arg(ap, size_t)); - else if (flag_t) - fprintf(stderr, str, va_arg(ap, ptrdiff_t)); - else if (flag_l == 0) - fprintf(stderr, str, va_arg(ap, int)); - else if (flag_l == 1) - fprintf(stderr, str, va_arg(ap, long)); - else - fprintf(stderr, str, va_arg(ap, long long)); - - str[len+1] = last; - break; - - case 'e': - case 'f': - case 'F': - case 'g': - case 'G': - case 'a': - case 'A': - last = str[len+1]; - str[len+1] = 0; - - if (flag_L) - fprintf(stderr, str, va_arg(ap, long double)); - else - fprintf(stderr, str, va_arg(ap, double)); - - str[len+1] = last; - break; - - case 'c': - last = str[len+1]; - str[len+1] = 0; - - fprintf(stderr, str, va_arg(ap, int)); - - str[len+1] = last; - break; - - case 's': - case 'p': - last = str[len+1]; - str[len+1] = 0; - - fprintf(stderr, str, va_arg(ap, void*)); - - str[len+1] = last; - break; - - case 'm': - last = str[len+1]; - str[len+1] = 0; - - fprintf(stderr, str); - - str[len+1] = last; - break; - - case 'E': - eth_addr = va_arg(ap, const fastd_eth_addr*); - - if (eth_addr) { - fprintf(stderr, "%02x:%02x:%02x:%02x:%02x:%02x", - eth_addr->data[0], eth_addr->data[1], eth_addr->data[2], - eth_addr->data[3], eth_addr->data[4], eth_addr->data[5]); - } - else { - fputs("(null)", stderr); - } - break; - - case 'P': - p = va_arg(ap, const fastd_peer*); - - if (p) - print_peer_str(ctx, (const fastd_peer*)p); - else - fputs("(null)", stderr); - break; - - case 'I': - p = va_arg(ap, const fastd_peer_address*); - - if (p) - print_peer_address(ctx, (const fastd_peer_address*)p); - else - fputs("(null)", stderr); - break; - - default: - finished = false; - } + format++; + + switch(*format) { + case 'i': + buffer += snprintf_safe(buffer, buffer_end-buffer, "%i", va_arg(ap, int)); + break; + + case 'u': + buffer += snprintf_safe(buffer, buffer_end-buffer, "%u", va_arg(ap, unsigned int)); + break; - if (finished) { - str += len; - break; + case 's': + buffer += snprintf_safe(buffer, buffer_end-buffer, "%s", va_arg(ap, char*)); + break; + + case 'E': + eth_addr = va_arg(ap, const fastd_eth_addr*); + + if (eth_addr) { + buffer += snprintf_safe(buffer, buffer_end-buffer, "%02x:%02x:%02x:%02x:%02x:%02x", + eth_addr->data[0], eth_addr->data[1], eth_addr->data[2], + eth_addr->data[3], eth_addr->data[4], eth_addr->data[5]); } + else { + buffer += snprintf_safe(buffer, buffer_end-buffer, "(null)"); + } + break; + + case 'P': + p = va_arg(ap, const fastd_peer*); + + if (p) + buffer += snprint_peer_str(ctx, buffer, buffer_end-buffer, (const fastd_peer*)p); + else + buffer += snprintf_safe(buffer, buffer_end-buffer, "(null)"); + break; + + case 'I': + p = va_arg(ap, const fastd_peer_address*); + + if (p) + buffer += snprint_peer_address(ctx, buffer, buffer_end-buffer, (const fastd_peer_address*)p); + else + buffer += snprintf_safe(buffer, buffer_end-buffer, "(null)"); + break; + + default: + pr_warn(ctx, "fastd_vsnprintf: unknown format conversion specifier '%c'", *format); + *buffer_start = 0; + return -1; } } - free(format_dup); + if (buffer < buffer_end) + *buffer = 0; - va_end(ap); + return buffer-buffer_start; } -- cgit v1.2.3