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
© 2016 - 2025 Red Hat, Inc.