From 25d26f67fc24c8be5b3b4a59a51cc9690d3201e8 Mon Sep 17 00:00:00 2001
From: Vincent Becker <vincentx.becker@intel.com>
Date: Thu, 24 Feb 2011 16:56:43 +0100
Subject: [PATCH] Format log messages with generic prepended and appended for all log targets, including the new one to file descriptor.
 Signed-off-by: Vincent Becker <vincentx.becker@intel.com>
 Metadata and append_data are new buffers created to prepend and append log info.
 Depending on the target, info filled is different. When writing effectively the log,
 it ensures that one call to a write function is necessary with the appropriate text t and append_data if needed.

---
 src/pulsecore/log.c |  140 +++++++++++++++++++++++++++++++++-----------------
 1 files changed, 92 insertions(+), 48 deletions(-)

diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index f5472c4..6d050e5 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -70,6 +70,7 @@ static pa_log_level_t maximum_level = PA_LOG_ERROR, maximum_level_override = PA_
 static unsigned show_backtrace = 0, show_backtrace_override = 0, skip_backtrace = 0;
 static pa_log_flags_t flags = 0, flags_override = 0;
 static pa_bool_t no_rate_limit = FALSE;
+static int fdlog = -1;
 
 #ifdef HAVE_SYSLOG_H
 static const int level_to_syslog[] = {
@@ -132,12 +133,6 @@ void pa_log_set_show_backtrace(unsigned nlevels) {
     show_backtrace = nlevels;
 }
 
-void pa_log_set_fd(int fd) {
-    pa_assert(fd >= 0);
-
-    fdlog = fd;
-}
-
 void pa_log_set_skip_backtrace(unsigned nlevels) {
     skip_backtrace = nlevels;
 }
@@ -275,10 +270,12 @@ void pa_log_levelv_meta(
     pa_log_level_t _maximum_level;
     unsigned _show_backtrace;
     pa_log_flags_t _flags;
+    char *local_t;
+    int metadata_length;
 
     /* We don't use dynamic memory allocation here to minimize the hit
      * in RT threads */
-    char text[16*1024], location[128], timestamp[32];
+    char text[16*1024], location[128], timestamp[32], metadata[256], append_data[256];
 
     pa_assert(level < PA_LOG_LEVEL_MAX);
     pa_assert(format);
@@ -295,8 +292,6 @@ void pa_log_levelv_meta(
         return;
     }
 
-    pa_vsnprintf(text, sizeof(text), format, ap);
-
     if ((_flags & PA_LOG_PRINT_META) && file && line > 0 && func)
         pa_snprintf(location, sizeof(location), "[%s:%i %s()] ", file, line, func);
     else if ((_flags & (PA_LOG_PRINT_META|PA_LOG_PRINT_FILE)) && file)
@@ -336,10 +331,76 @@ void pa_log_levelv_meta(
         bt = get_backtrace(_show_backtrace);
 #endif
 
-    if (!pa_utf8_valid(text))
+    switch (_target) {
+
+    case PA_LOG_STDERR: {
+        const char *prefix = "", *suffix = "", *grey = "";
+
+#ifndef OS_IS_WIN32
+        /* Yes indeed. Useless, but fun! */
+        if ((_flags & PA_LOG_COLORS) && isatty(STDERR_FILENO)) {
+            if (level <= PA_LOG_ERROR)
+                prefix = "\x1B[1;31m";
+            else if (level <= PA_LOG_WARN)
+                prefix = "\x1B[1m";
+
+            if (bt)
+                grey = "\x1B[2m";
+
+            if (grey[0] || prefix[0])
+                suffix = "\x1B[0m";
+        }
+#endif
+        if (_flags & PA_LOG_PRINT_LEVEL)
+            pa_snprintf(metadata, sizeof(metadata), "%s%c: %s%s", timestamp, level_to_char[level], location, prefix);
+        else
+            pa_snprintf(metadata, sizeof(metadata), "%s%s%s", timestamp, location, prefix);
+
+        pa_snprintf(append_data, sizeof(append_data), "%s%s%s", grey, pa_strempty(bt), suffix);
+
+        break;
+    }
+
+#ifdef HAVE_SYSLOG_H
+    case PA_LOG_SYSLOG: {
+        pa_snprintf(metadata, sizeof(metadata), "%s%s", timestamp, location);
+        pa_snprintf(append_data, sizeof(append_data) ,"%s", pa_strempty(bt));
+
+        break;
+    }
+#endif
+
+    case PA_LOG_FILED: {
+        pa_snprintf(metadata, sizeof(metadata), "\n%c %s%s", level_to_char[level], timestamp, location);
+
+        append_data[0] = 0;
+
+        break;
+    }
+
+    default:
+        metadata[0] = 0;
+        append_data[0] = 0;
+
+        break;
+    }
+
+    metadata_length = strlen(metadata);
+
+    /* Format text at metadata_length position */
+    pa_vsnprintf(&text[metadata_length], sizeof(text) - metadata_length, format, ap);
+
+    if (!pa_utf8_valid(&text[metadata_length]))
         pa_logl(level, "Invalid UTF-8 string following below:");
 
-    for (t = text; t; t = n) {
+    /* We shouldn't be using dynamic allocation here to
+     * minimize the hit in RT threads */
+    if ((local_t = pa_utf8_to_locale(&text[metadata_length]))) {
+        strcpy(&text[metadata_length], local_t);
+        pa_xfree(local_t);
+    }
+
+    for (t = &text[metadata_length]; t; t = n) {
         if ((n = strchr(t, '\n'))) {
             *n = 0;
             n++;
@@ -349,59 +410,42 @@ void pa_log_levelv_meta(
         if (t[strspn(t, "\t ")] == 0)
             continue;
 
-        switch (_target) {
-
-            case PA_LOG_STDERR: {
-                const char *prefix = "", *suffix = "", *grey = "";
-                char *local_t;
-
-#ifndef OS_IS_WIN32
-                /* Yes indeed. Useless, but fun! */
-                if ((_flags & PA_LOG_COLORS) && isatty(STDERR_FILENO)) {
-                    if (level <= PA_LOG_ERROR)
-                        prefix = "\x1B[1;31m";
-                    else if (level <= PA_LOG_WARN)
-                        prefix = "\x1B[1m";
-
-                    if (bt)
-                        grey = "\x1B[2m";
-
-                    if (grey[0] || prefix[0])
-                        suffix = "\x1B[0m";
-                }
-#endif
+        /* Rewind to the start of the t buffer */
+        t -= metadata_length;
 
-                /* We shouldn't be using dynamic allocation here to
-                 * minimize the hit in RT threads */
-                if ((local_t = pa_utf8_to_locale(t)))
-                    t = local_t;
+        /* Prepend metadata into t */
+        memcpy(t, metadata, metadata_length);
 
-                if (_flags & PA_LOG_PRINT_LEVEL)
-                    fprintf(stderr, "%s%c: %s%s%s%s%s%s\n", timestamp, level_to_char[level], location, prefix, t, grey, pa_strempty(bt), suffix);
-                else
-                    fprintf(stderr, "%s%s%s%s%s%s%s\n", timestamp, location, prefix, t, grey, pa_strempty(bt), suffix);
+        switch (_target) {
 
-                pa_xfree(local_t);
+            case PA_LOG_STDERR: {
+                fprintf(stderr, "%s%s\n", t, append_data);
 
                 break;
             }
 
 #ifdef HAVE_SYSLOG_H
             case PA_LOG_SYSLOG: {
-                char *local_t;
-
                 openlog(ident, LOG_PID, LOG_USER);
 
-                if ((local_t = pa_utf8_to_locale(t)))
-                    t = local_t;
-
-                syslog(level_to_syslog[level], "%s%s%s%s", timestamp, location, t, pa_strempty(bt));
-                pa_xfree(local_t);
+                syslog(level_to_syslog[level], "%s%s", t, append_data);
 
                 break;
             }
 #endif
 
+            case PA_LOG_FILED: {
+                if (fdlog != -1) {
+                    if (write(fdlog, t, strlen(t)) < 0) {
+                        saved_errno = errno;
+                        pa_close(fdlog);
+                        fdlog = -1;
+                    }
+                }
+
+                break;
+            }
+
             case PA_LOG_NULL:
             default:
                 break;
-- 
1.7.2.3

