summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-04-21 10:25:50 +0200
committerLennart Poettering <lennart@poettering.net>2020-04-21 17:07:43 +0200
commit052740e2e35cf9bbb56e8809050faf0c6ee60cb4 (patch)
treea75b2182b1a7c1acbc4918567d7d546eac9adeb0 /src
parentcore: automatically add udev dependency for units using RootImage= (diff)
downloadsystemd-052740e2e35cf9bbb56e8809050faf0c6ee60cb4.tar.xz
systemd-052740e2e35cf9bbb56e8809050faf0c6ee60cb4.zip
log-control-api: add generic D-Bus interface for querying/setting log level/target
Let's define a new, generic bus interface that any daemon can implement for querying/setting the log level. We can turn this into something more powerful later on, but for now, only expose three properties: the log level, log target and the syslog identifier (with the former two being writable). This is supposed to be generic, so that it can be implemented by 3rd party daemons too, eventually.
Diffstat (limited to 'src')
-rw-r--r--src/shared/bus-log-control-api.c123
-rw-r--r--src/shared/bus-log-control-api.h13
-rw-r--r--src/shared/meson.build6
3 files changed, 140 insertions, 2 deletions
diff --git a/src/shared/bus-log-control-api.c b/src/shared/bus-log-control-api.c
new file mode 100644
index 0000000000..ffc52c7774
--- /dev/null
+++ b/src/shared/bus-log-control-api.c
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "bus-log-control-api.h"
+#include "bus-util.h"
+#include "log.h"
+#include "sd-bus.h"
+#include "syslog-util.h"
+
+int bus_property_get_log_level(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ _cleanup_free_ char *t = NULL;
+ int r;
+
+ assert(bus);
+ assert(reply);
+
+ r = log_level_to_string_alloc(log_get_max_level(), &t);
+ if (r < 0)
+ return r;
+
+ return sd_bus_message_append(reply, "s", t);
+}
+
+int bus_property_set_log_level(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *value,
+ void *userdata,
+ sd_bus_error *error) {
+
+ const char *t;
+ int r;
+
+ assert(bus);
+ assert(value);
+
+ r = sd_bus_message_read(value, "s", &t);
+ if (r < 0)
+ return r;
+
+ r = log_level_from_string(t);
+ if (r < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t);
+
+ log_info("Setting log level to %s.", t);
+ log_set_max_level(r);
+
+ return 0;
+}
+
+BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_log_target, "s", log_target_to_string(log_get_target()));
+
+int bus_property_set_log_target(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *value,
+ void *userdata,
+ sd_bus_error *error) {
+
+ LogTarget target;
+ const char *t;
+ int r;
+
+ assert(bus);
+ assert(value);
+
+ r = sd_bus_message_read(value, "s", &t);
+ if (r < 0)
+ return r;
+
+ target = log_target_from_string(t);
+ if (target < 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log target '%s'", t);
+
+ log_info("Setting log target to %s.", log_target_to_string(target));
+ log_set_target(target);
+ log_open();
+
+ return 0;
+}
+
+BUS_DEFINE_PROPERTY_GET_GLOBAL(bus_property_get_syslog_identifier, "s", program_invocation_short_name);
+
+static const sd_bus_vtable log_control_vtable[] = {
+ SD_BUS_VTABLE_START(0),
+
+ SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", bus_property_get_log_level, bus_property_set_log_level, 0, 0),
+ SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", bus_property_get_log_target, bus_property_set_log_target, 0, 0),
+ SD_BUS_PROPERTY("SyslogIdentifier", "s", bus_property_get_syslog_identifier, 0, 0),
+
+ /* One of those days we might want to add a similar, second interface to cover common service
+ * operations such as Reload(), Reexecute(), Exit() … and maybe some properties exposing version
+ * number and other meta-data of the service. */
+
+ SD_BUS_VTABLE_END,
+};
+
+int bus_log_control_api_register(sd_bus *bus) {
+ int r;
+
+ r = sd_bus_add_object_vtable(
+ bus,
+ NULL,
+ "/org/freedesktop/LogControl1",
+ "org.freedesktop.LogControl1",
+ log_control_vtable, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to register service API object: %m");
+
+ return 0;
+}
diff --git a/src/shared/bus-log-control-api.h b/src/shared/bus-log-control-api.h
new file mode 100644
index 0000000000..a6fb2757c5
--- /dev/null
+++ b/src/shared/bus-log-control-api.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "sd-bus.h"
+
+int bus_log_control_api_register(sd_bus *bus);
+
+int bus_property_get_log_level(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+int bus_property_set_log_level(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
+
+int bus_property_get_log_target(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+int bus_property_set_log_target(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+
+int bus_property_get_syslog_identifier(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
diff --git a/src/shared/meson.build b/src/shared/meson.build
index d1832a1f53..483148492c 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -23,14 +23,16 @@ shared_sources = files('''
bpf-program.h
bridge-util.c
bridge-util.h
+ bus-log-control-api.c
+ bus-log-control-api.h
+ bus-polkit.c
+ bus-polkit.h
bus-unit-procs.c
bus-unit-procs.h
bus-unit-util.c
bus-unit-util.h
bus-util.c
bus-util.h
- bus-polkit.c
- bus-polkit.h
bus-wait-for-jobs.c
bus-wait-for-jobs.h
bus-wait-for-units.c