145 lines
5.2 KiB
C
145 lines
5.2 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include "bus-error.h"
|
|
#include "bus-locator.h"
|
|
#include "pretty-print.h"
|
|
#include "syslog-util.h"
|
|
#include "systemctl-log-setting.h"
|
|
#include "systemctl-util.h"
|
|
#include "systemctl.h"
|
|
|
|
static void give_log_control1_hint(const char *name) {
|
|
_cleanup_free_ char *link = NULL;
|
|
|
|
if (arg_quiet)
|
|
return;
|
|
|
|
(void) terminal_urlify_man("org.freedesktop.LogControl1", "5", &link);
|
|
|
|
log_notice("Hint: the service must declare BusName= and implement the appropriate D-Bus interface.\n"
|
|
" See the %s for details.", link ?: "org.freedesktop.LogControl1(5) man page");
|
|
}
|
|
|
|
static int log_setting_internal(sd_bus *bus, const BusLocator* bloc, const char *verb, const char *value) {
|
|
assert(bus);
|
|
assert(STR_IN_SET(verb, "log-level", "log-target", "service-log-level", "service-log-target"));
|
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
bool level = endswith(verb, "log-level");
|
|
int r;
|
|
|
|
if (value) {
|
|
if (level) {
|
|
if (log_level_from_string(value) < 0)
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
"\"%s\" is not a valid log level.", value);
|
|
}
|
|
|
|
r = bus_set_property(bus, bloc,
|
|
level ? "LogLevel" : "LogTarget",
|
|
&error, "s", value);
|
|
if (r >= 0)
|
|
return 0;
|
|
|
|
log_error_errno(r, "Failed to set log %s of %s to %s: %s",
|
|
level ? "level" : "target",
|
|
bloc->destination, value, bus_error_message(&error, r));
|
|
} else {
|
|
_cleanup_free_ char *t = NULL;
|
|
|
|
r = bus_get_property_string(bus, bloc,
|
|
level ? "LogLevel" : "LogTarget",
|
|
&error, &t);
|
|
if (r >= 0) {
|
|
puts(t);
|
|
return 0;
|
|
}
|
|
|
|
log_error_errno(r, "Failed to get log %s of %s: %s",
|
|
level ? "level" : "target",
|
|
bloc->destination, bus_error_message(&error, r));
|
|
}
|
|
|
|
if (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD,
|
|
SD_BUS_ERROR_UNKNOWN_OBJECT,
|
|
SD_BUS_ERROR_UNKNOWN_INTERFACE,
|
|
SD_BUS_ERROR_UNKNOWN_PROPERTY))
|
|
give_log_control1_hint(bloc->destination);
|
|
return r;
|
|
}
|
|
|
|
int log_setting(int argc, char *argv[], void *userdata) {
|
|
sd_bus *bus;
|
|
int r;
|
|
|
|
assert(argc >= 1 && argc <= 2);
|
|
|
|
r = acquire_bus(BUS_MANAGER, &bus);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
return log_setting_internal(bus, bus_systemd_mgr, argv[0], argv[1]);
|
|
}
|
|
|
|
static int service_name_to_dbus(sd_bus *bus, const char *name, char **ret_dbus_name) {
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
_cleanup_free_ char *bus_name = NULL;
|
|
int r;
|
|
|
|
/* First, look for the BusName= property */
|
|
_cleanup_free_ char *dbus_path = unit_dbus_path_from_name(name);
|
|
if (!dbus_path)
|
|
return log_oom();
|
|
|
|
r = sd_bus_get_property_string(
|
|
bus,
|
|
"org.freedesktop.systemd1",
|
|
dbus_path,
|
|
"org.freedesktop.systemd1.Service",
|
|
"BusName",
|
|
&error,
|
|
&bus_name);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to obtain BusName= property of %s: %s",
|
|
name, bus_error_message(&error, r));
|
|
|
|
if (isempty(bus_name)) {
|
|
log_error("Unit %s doesn't declare BusName=.", name);
|
|
give_log_control1_hint(name);
|
|
return -ENOLINK;
|
|
}
|
|
|
|
*ret_dbus_name = TAKE_PTR(bus_name);
|
|
return 0;
|
|
}
|
|
|
|
int service_log_setting(int argc, char *argv[], void *userdata) {
|
|
sd_bus *bus;
|
|
_cleanup_free_ char *unit = NULL, *dbus_name = NULL;
|
|
int r;
|
|
|
|
assert(argc >= 2 && argc <= 3);
|
|
|
|
r = acquire_bus(BUS_FULL, &bus);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
r = unit_name_mangle_with_suffix(argv[1], argv[0],
|
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
|
".service", &unit);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to mangle unit name: %m");
|
|
|
|
r = service_name_to_dbus(bus, unit, &dbus_name);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
const BusLocator bloc = {
|
|
.destination = dbus_name,
|
|
.path = "/org/freedesktop/LogControl1",
|
|
.interface = "org.freedesktop.LogControl1",
|
|
};
|
|
|
|
return log_setting_internal(bus, &bloc, argv[0], argv[2]);
|
|
}
|