[RFC 1/4] util: Introduce LogOutput

Richard Henderson posted 4 patches 3 weeks, 5 days ago
[RFC 1/4] util: Introduce LogOutput
Posted by Richard Henderson 3 weeks, 5 days ago
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/monitor/monitor.h |  4 +++
 include/qemu/log-output.h | 14 ++++++++++
 monitor/monitor.c         | 54 +++++++++++++++++++++++++++++++--------
 stubs/error-printf.c      | 11 ++++++++
 util/log.c                |  7 +++++
 5 files changed, 79 insertions(+), 11 deletions(-)
 create mode 100644 include/qemu/log-output.h

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index c3740ec616..8c4d73592f 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -4,6 +4,7 @@
 #include "block/block.h"
 #include "qapi/qapi-types-misc.h"
 #include "qemu/readline.h"
+#include "qemu/log-output.h"
 #include "exec/hwaddr.h"
 
 typedef struct MonitorHMP MonitorHMP;
@@ -62,4 +63,7 @@ void monitor_register_hmp_info_hrt(const char *name,
 int error_vprintf_unless_qmp(const char *fmt, va_list ap) G_GNUC_PRINTF(1, 0);
 int error_printf_unless_qmp(const char *fmt, ...) G_GNUC_PRINTF(1, 2);
 
+const LogOutput *error_log_output(void **popaque);
+const LogOutput *error_log_output_unless_qmp(void **popaque);
+
 #endif /* MONITOR_H */
diff --git a/include/qemu/log-output.h b/include/qemu/log-output.h
new file mode 100644
index 0000000000..1d502aae77
--- /dev/null
+++ b/include/qemu/log-output.h
@@ -0,0 +1,14 @@
+#ifndef QEMU_LOG_OUTPUT_H
+#define QEMU_LOG_OUTPUT_H 1
+
+typedef int LogOutputVararg(void *, const char *, ...) G_GNUC_PRINTF(2, 3);
+typedef int LogOutputVaList(void *, const char *, va_list) G_GNUC_PRINTF(2, 0);
+
+typedef struct LogOutput {
+    LogOutputVararg *print;
+    LogOutputVaList *vprint;
+} LogOutput;
+
+extern const LogOutput log_output_stdio;
+
+#endif
diff --git a/monitor/monitor.c b/monitor/monitor.c
index da54e1b1ce..71a3d62e0f 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -268,28 +268,60 @@ void monitor_printc(Monitor *mon, int c)
     monitor_printf(mon, "'");
 }
 
+static const LogOutput log_output_monitor = {
+    /* Abuse the Monitor* argument of monitor_printf as void* opaque. */
+    (LogOutputVararg *)monitor_printf,
+    (LogOutputVaList *)monitor_vprintf,
+};
+
+const LogOutput *error_log_output(void **popaque)
+{
+    Monitor *cur_mon = monitor_cur();
+
+    if (cur_mon && !monitor_cur_is_qmp()) {
+        *popaque = cur_mon;
+        return &log_output_monitor;
+    }
+
+    *popaque = stderr;
+    return &log_output_stdio;
+}
+
+const LogOutput *error_log_output_unless_qmp(void **popaque)
+{
+    Monitor *cur_mon = monitor_cur();
+
+    if (!cur_mon) {
+        *popaque = stderr;
+        return &log_output_stdio;
+    }
+    if (!monitor_cur_is_qmp()) {
+        *popaque = cur_mon;
+        return &log_output_monitor;
+    }
+
+    *popaque = NULL;
+    return NULL;
+}
+
 /*
  * Print to current monitor if we have one, else to stderr.
  */
 int error_vprintf(const char *fmt, va_list ap)
 {
-    Monitor *cur_mon = monitor_cur();
+    void *opaque;
+    const LogOutput *l = error_log_output(&opaque);
 
-    if (cur_mon && !monitor_cur_is_qmp()) {
-        return monitor_vprintf(cur_mon, fmt, ap);
-    }
-    return vfprintf(stderr, fmt, ap);
+    return l->vprint(opaque, fmt, ap);
 }
 
 int error_vprintf_unless_qmp(const char *fmt, va_list ap)
 {
-    Monitor *cur_mon = monitor_cur();
+    void *opaque;
+    const LogOutput *l = error_log_output_unless_qmp(&opaque);
 
-    if (!cur_mon) {
-        return vfprintf(stderr, fmt, ap);
-    }
-    if (!monitor_cur_is_qmp()) {
-        return monitor_vprintf(cur_mon, fmt, ap);
+    if (l) {
+        return l->vprint(opaque, fmt, ap);
     }
     return -1;
 }
diff --git a/stubs/error-printf.c b/stubs/error-printf.c
index 0e326d8010..82e4756bda 100644
--- a/stubs/error-printf.c
+++ b/stubs/error-printf.c
@@ -21,3 +21,14 @@ int error_vprintf_unless_qmp(const char *fmt, va_list ap)
 {
     return error_vprintf(fmt, ap);
 }
+
+const LogOutput *error_log_output(void **popaque)
+{
+    *popaque = stderr;
+    return &log_output_stdio;
+}
+
+const LogOutput *error_log_output_unless_qmp(void **popaque)
+{
+    return error_log_output(popaque);
+}
diff --git a/util/log.c b/util/log.c
index fc900cde0c..4b5953dcc7 100644
--- a/util/log.c
+++ b/util/log.c
@@ -28,6 +28,7 @@
 #include "qemu/thread.h"
 #include "qemu/lockable.h"
 #include "qemu/rcu.h"
+#include "qemu/log-output.h"
 #ifdef CONFIG_LINUX
 #include <sys/syscall.h>
 #endif
@@ -592,3 +593,9 @@ ssize_t rust_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
     return ret < 0 ? -errno : 0;
 }
 #endif
+
+const LogOutput log_output_stdio = {
+    /* Abuse the FILE* argument of fprintf as void* opaque. */
+    (LogOutputVararg *)fprintf,
+    (LogOutputVaList *)vfprintf,
+};
-- 
2.43.0