1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include "bus-locator.h"
5 #include "pretty-print.h"
6 #include "syslog-util.h"
7 #include "systemctl-log-setting.h"
8 #include "systemctl-util.h"
11 static void give_log_control1_hint(const char *name
) {
12 _cleanup_free_
char *link
= NULL
;
17 (void) terminal_urlify_man("org.freedesktop.LogControl1", "5", &link
);
19 log_notice("Hint: the service must declare BusName= and implement the appropriate D-Bus interface.\n"
20 " See the %s for details.", link
?: "org.freedesktop.LogControl1(5) man page");
23 static int log_setting_internal(sd_bus
*bus
, const BusLocator
* bloc
, const char *verb
, const char *value
) {
25 assert(STR_IN_SET(verb
, "log-level", "log-target", "service-log-level", "service-log-target"));
27 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
28 bool level
= endswith(verb
, "log-level");
33 if (log_level_from_string(value
) < 0)
34 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
),
35 "\"%s\" is not a valid log level.", value
);
38 r
= bus_set_property(bus
, bloc
,
39 level
? "LogLevel" : "LogTarget",
44 log_error_errno(r
, "Failed to set log %s of %s to %s: %s",
45 level
? "level" : "target",
46 bloc
->destination
, value
, bus_error_message(&error
, r
));
48 _cleanup_free_
char *t
= NULL
;
50 r
= bus_get_property_string(bus
, bloc
,
51 level
? "LogLevel" : "LogTarget",
58 log_error_errno(r
, "Failed to get log %s of %s: %s",
59 level
? "level" : "target",
60 bloc
->destination
, bus_error_message(&error
, r
));
63 if (sd_bus_error_has_names(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
,
64 SD_BUS_ERROR_UNKNOWN_OBJECT
,
65 SD_BUS_ERROR_UNKNOWN_INTERFACE
,
66 SD_BUS_ERROR_UNKNOWN_PROPERTY
))
67 give_log_control1_hint(bloc
->destination
);
71 int log_setting(int argc
, char *argv
[], void *userdata
) {
75 assert(argc
>= 1 && argc
<= 2);
77 r
= acquire_bus(BUS_MANAGER
, &bus
);
81 return log_setting_internal(bus
, bus_systemd_mgr
, argv
[0], argv
[1]);
84 static int service_name_to_dbus(sd_bus
*bus
, const char *name
, char **ret_dbus_name
) {
85 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
86 _cleanup_free_
char *bus_name
= NULL
;
89 /* First, look for the BusName= property */
90 _cleanup_free_
char *dbus_path
= unit_dbus_path_from_name(name
);
94 r
= sd_bus_get_property_string(
96 "org.freedesktop.systemd1",
98 "org.freedesktop.systemd1.Service",
103 return log_error_errno(r
, "Failed to obtain BusName= property of %s: %s",
104 name
, bus_error_message(&error
, r
));
106 if (isempty(bus_name
)) {
107 log_error("Unit %s doesn't declare BusName=.", name
);
108 give_log_control1_hint(name
);
112 *ret_dbus_name
= TAKE_PTR(bus_name
);
116 int service_log_setting(int argc
, char *argv
[], void *userdata
) {
118 _cleanup_free_
char *unit
= NULL
, *dbus_name
= NULL
;
121 assert(argc
>= 2 && argc
<= 3);
123 r
= acquire_bus(BUS_FULL
, &bus
);
127 r
= unit_name_mangle_with_suffix(argv
[1], argv
[0],
128 arg_quiet
? 0 : UNIT_NAME_MANGLE_WARN
,
131 return log_error_errno(r
, "Failed to mangle unit name: %m");
133 r
= service_name_to_dbus(bus
, unit
, &dbus_name
);
137 const BusLocator bloc
= {
138 .destination
= dbus_name
,
139 .path
= "/org/freedesktop/LogControl1",
140 .interface
= "org.freedesktop.LogControl1",
143 return log_setting_internal(bus
, &bloc
, argv
[0], argv
[2]);