]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl-log-setting.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / systemctl / systemctl-log-setting.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "bus-error.h"
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"
9 #include "systemctl.h"
10
11 static void give_log_control1_hint(const char *name) {
12 _cleanup_free_ char *link = NULL;
13
14 if (arg_quiet)
15 return;
16
17 (void) terminal_urlify_man("org.freedesktop.LogControl1", "5", &link);
18
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");
21 }
22
23 static int log_setting_internal(sd_bus *bus, const BusLocator* bloc, const char *verb, const char *value) {
24 assert(bus);
25 assert(STR_IN_SET(verb, "log-level", "log-target", "service-log-level", "service-log-target"));
26
27 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
28 bool level = endswith(verb, "log-level");
29 int r;
30
31 if (value) {
32 if (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);
36 }
37
38 r = bus_set_property(bus, bloc,
39 level ? "LogLevel" : "LogTarget",
40 &error, "s", value);
41 if (r >= 0)
42 return 0;
43
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));
47 } else {
48 _cleanup_free_ char *t = NULL;
49
50 r = bus_get_property_string(bus, bloc,
51 level ? "LogLevel" : "LogTarget",
52 &error, &t);
53 if (r >= 0) {
54 puts(t);
55 return 0;
56 }
57
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));
61 }
62
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);
68 return r;
69 }
70
71 int log_setting(int argc, char *argv[], void *userdata) {
72 sd_bus *bus;
73 int r;
74
75 assert(argc >= 1 && argc <= 2);
76
77 r = acquire_bus(BUS_MANAGER, &bus);
78 if (r < 0)
79 return r;
80
81 return log_setting_internal(bus, bus_systemd_mgr, argv[0], argv[1]);
82 }
83
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;
87 int r;
88
89 /* First, look for the BusName= property */
90 _cleanup_free_ char *dbus_path = unit_dbus_path_from_name(name);
91 if (!dbus_path)
92 return log_oom();
93
94 r = sd_bus_get_property_string(
95 bus,
96 "org.freedesktop.systemd1",
97 dbus_path,
98 "org.freedesktop.systemd1.Service",
99 "BusName",
100 &error,
101 &bus_name);
102 if (r < 0)
103 return log_error_errno(r, "Failed to obtain BusName= property of %s: %s",
104 name, bus_error_message(&error, r));
105
106 if (isempty(bus_name)) {
107 log_error("Unit %s doesn't declare BusName=.", name);
108 give_log_control1_hint(name);
109 return -ENOLINK;
110 }
111
112 *ret_dbus_name = TAKE_PTR(bus_name);
113 return 0;
114 }
115
116 int service_log_setting(int argc, char *argv[], void *userdata) {
117 sd_bus *bus;
118 _cleanup_free_ char *unit = NULL, *dbus_name = NULL;
119 int r;
120
121 assert(argc >= 2 && argc <= 3);
122
123 r = acquire_bus(BUS_FULL, &bus);
124 if (r < 0)
125 return r;
126
127 r = unit_name_mangle_with_suffix(argv[1], argv[0],
128 arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
129 ".service", &unit);
130 if (r < 0)
131 return log_error_errno(r, "Failed to mangle unit name: %m");
132
133 r = service_name_to_dbus(bus, unit, &dbus_name);
134 if (r < 0)
135 return r;
136
137 const BusLocator bloc = {
138 .destination = dbus_name,
139 .path = "/org/freedesktop/LogControl1",
140 .interface = "org.freedesktop.LogControl1",
141 };
142
143 return log_setting_internal(bus, &bloc, argv[0], argv[2]);
144 }