]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/log.c
remap: Change remapping function argument type from void to int16_t / float as approp...
[pulseaudio] / src / pulsecore / log.c
index 49f1b5b0ce4c175c3097f48383ebde22524c75d6..cf96dcef1a6721118bcd6793c3cc76be6bfbf41a 100644 (file)
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 
 #ifdef HAVE_EXECINFO_H
 #include <execinfo.h>
 #include <syslog.h>
 #endif
 
+#ifdef HAVE_JOURNAL
+#include <systemd/sd-journal.h>
+#endif
+
 #include <pulse/gccmacro.h>
 #include <pulse/rtclock.h>
 #include <pulse/utf8.h>
@@ -89,6 +94,18 @@ static const int level_to_syslog[] = {
 };
 #endif
 
+/* These are actually equivalent to the syslog ones
+ * but we don't want to depend on syslog.h */
+#ifdef HAVE_JOURNAL
+static const int level_to_journal[] = {
+    [PA_LOG_ERROR]  = 3,
+    [PA_LOG_WARN]   = 4,
+    [PA_LOG_NOTICE] = 5,
+    [PA_LOG_INFO]   = 6,
+    [PA_LOG_DEBUG]  = 7
+};
+#endif
+
 static const char level_to_char[] = {
     [PA_LOG_ERROR] = 'E',
     [PA_LOG_WARN] = 'W',
@@ -128,6 +145,9 @@ int pa_log_set_target(pa_log_target *t) {
     switch (t->type) {
         case PA_LOG_STDERR:
         case PA_LOG_SYSLOG:
+#ifdef HAVE_JOURNAL
+        case PA_LOG_JOURNAL:
+#endif
         case PA_LOG_NULL:
             break;
         case PA_LOG_FILE:
@@ -317,6 +337,20 @@ static void init_defaults(void) {
     } PA_ONCE_END;
 }
 
+#ifdef HAVE_SYSLOG_H
+static void log_syslog(pa_log_level_t level, char *t, char *timestamp, char *location, char *bt) {
+    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);
+}
+#endif
+
 void pa_log_levelv_meta(
         pa_log_level_t level,
         const char*file,
@@ -449,29 +483,56 @@ void pa_log_levelv_meta(
             }
 
 #ifdef HAVE_SYSLOG_H
-            case PA_LOG_SYSLOG: {
-                char *local_t;
-
-                openlog(ident, LOG_PID, LOG_USER);
+            case PA_LOG_SYSLOG:
+                log_syslog(level, t, timestamp, location, bt);
+                break;
+#endif
 
-                if ((local_t = pa_utf8_to_locale(t)))
-                    t = local_t;
+#ifdef HAVE_JOURNAL
+            case PA_LOG_JOURNAL:
+                if (sd_journal_send("MESSAGE=%s", t,
+                                "PRIORITY=%i", level_to_journal[level],
+                                "CODE_FILE=%s", file,
+                                "CODE_FUNC=%s", func,
+                                "CODE_LINE=%d", line,
+                                NULL) < 0) {
+#ifdef HAVE_SYSLOG_H
+                    pa_log_target new_target = { .type = PA_LOG_SYSLOG, .file = NULL };
 
-                syslog(level_to_syslog[level], "%s%s%s%s", timestamp, location, t, pa_strempty(bt));
-                pa_xfree(local_t);
+                    syslog(level_to_syslog[PA_LOG_ERROR], "%s%s%s", timestamp, __FILE__,
+                           "Error writing logs to the journal. Redirect log messages to syslog.");
+                    log_syslog(level, t, timestamp, location, bt);
+#else
+                    pa_log_target new_target = { .type = PA_LOG_STDERR, .file = NULL };
 
+                    saved_errno = errno;
+                    fprintf(stderr, "%s\n", "Error writing logs to the journal. Redirect log messages to console.");
+                    fprintf(stderr, "%s %s\n", metadata, t);
+#endif
+                    pa_log_set_target(&new_target);
+                }
                 break;
-            }
 #endif
 
             case PA_LOG_FILE:
             case PA_LOG_NEWFILE: {
+                char *local_t;
+
+                if ((local_t = pa_utf8_to_locale(t)))
+                    t = local_t;
+
                 if (log_fd >= 0) {
                     char metadata[256];
 
-                    pa_snprintf(metadata, sizeof(metadata), "\n%c %s %s", level_to_char[level], timestamp, location);
+                    if (_flags & PA_LOG_PRINT_LEVEL)
+                        pa_snprintf(metadata, sizeof(metadata), "%s%c: %s", timestamp, level_to_char[level], location);
+                    else
+                        pa_snprintf(metadata, sizeof(metadata), "%s%s", timestamp, location);
 
-                    if ((pa_write(log_fd, metadata, strlen(metadata), &write_type) < 0) || (pa_write(log_fd, t, strlen(t), &write_type) < 0)) {
+                    if ((pa_write(log_fd, metadata, strlen(metadata), &write_type) < 0)
+                            || (pa_write(log_fd, t, strlen(t), &write_type) < 0)
+                            || (bt && pa_write(log_fd, bt, strlen(bt), &write_type) < 0)
+                            || (pa_write(log_fd, "\n", 1, &write_type) < 0)) {
                         pa_log_target new_target = { .type = PA_LOG_STDERR, .file = NULL };
                         saved_errno = errno;
                         fprintf(stderr, "%s\n", "Error writing logs to a file descriptor. Redirect log messages to console.");
@@ -480,6 +541,8 @@ void pa_log_levelv_meta(
                     }
                 }
 
+                pa_xfree(local_t);
+
                 break;
             }
             case PA_LOG_NULL:
@@ -556,6 +619,10 @@ pa_log_target *pa_log_parse_target(const char *string) {
         t = pa_log_target_new(PA_LOG_STDERR, NULL);
     else if (pa_streq(string, "syslog"))
         t = pa_log_target_new(PA_LOG_SYSLOG, NULL);
+#ifdef HAVE_JOURNAL
+    else if (pa_streq(string, "journal"))
+        t = pa_log_target_new(PA_LOG_JOURNAL, NULL);
+#endif
     else if (pa_streq(string, "null"))
         t = pa_log_target_new(PA_LOG_NULL, NULL);
     else if (pa_startswith(string, "file:"))
@@ -580,6 +647,11 @@ char *pa_log_target_to_string(const pa_log_target *t) {
         case PA_LOG_SYSLOG:
             string = pa_xstrdup("syslog");
             break;
+#ifdef HAVE_JOURNAL
+        case PA_LOG_JOURNAL:
+            string = pa_xstrdup("journal");
+            break;
+#endif
         case PA_LOG_NULL:
             string = pa_xstrdup("null");
             break;