]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/systemctl/systemctl-logind.c
Merge pull request #30060 from poettering/analyze-archs
[thirdparty/systemd.git] / src / systemctl / systemctl-logind.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <unistd.h>
4
5 #include "sd-login.h"
6
7 #include "bus-error.h"
8 #include "bus-locator.h"
9 #include "login-util.h"
10 #include "process-util.h"
11 #include "systemctl-logind.h"
12 #include "systemctl-start-unit.h"
13 #include "systemctl-util.h"
14 #include "systemctl.h"
15 #include "terminal-util.h"
16 #include "user-util.h"
17
18 static int logind_set_wall_message(sd_bus *bus) {
19 #if ENABLE_LOGIND
20 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
21 _cleanup_free_ char *m = NULL;
22 int r;
23
24 assert(bus);
25
26 m = strv_join(arg_wall, " ");
27 if (!m)
28 return log_oom();
29
30 log_debug("%s wall message \"%s\".", arg_dry_run ? "Would set" : "Setting", m);
31 if (arg_dry_run)
32 return 0;
33
34 r = bus_call_method(bus, bus_login_mgr, "SetWallMessage", &error, NULL, "sb", m, !arg_no_wall);
35 if (r < 0)
36 return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
37 #endif
38 return 0;
39 }
40
41 /* Ask systemd-logind, which might grant access to unprivileged users through polkit */
42 int logind_reboot(enum action a) {
43 #if ENABLE_LOGIND
44 static const char* actions[_ACTION_MAX] = {
45 [ACTION_POWEROFF] = "PowerOff",
46 [ACTION_REBOOT] = "Reboot",
47 [ACTION_KEXEC] = "Reboot",
48 [ACTION_SOFT_REBOOT] = "Reboot",
49 [ACTION_HALT] = "Halt",
50 [ACTION_SUSPEND] = "Suspend",
51 [ACTION_HIBERNATE] = "Hibernate",
52 [ACTION_HYBRID_SLEEP] = "HybridSleep",
53 [ACTION_SUSPEND_THEN_HIBERNATE] = "SuspendThenHibernate",
54 [ACTION_SLEEP] = "Sleep",
55 };
56
57 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
58 uint64_t flags = 0;
59 sd_bus *bus;
60 int r;
61
62 assert(a >= 0);
63 assert(a < _ACTION_MAX);
64
65 if (!actions[a])
66 return -EINVAL;
67
68 r = acquire_bus(BUS_FULL, &bus);
69 if (r < 0)
70 return r;
71
72 polkit_agent_open_maybe();
73 (void) logind_set_wall_message(bus);
74
75 const char *method_with_flags = a == ACTION_SLEEP ? actions[a] : strjoina(actions[a], "WithFlags");
76
77 log_debug("%s org.freedesktop.login1.Manager %s dbus call.",
78 arg_dry_run ? "Would execute" : "Executing", method_with_flags);
79
80 if (arg_dry_run)
81 return 0;
82
83 SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
84 SET_FLAG(flags,
85 SD_LOGIND_REBOOT_VIA_KEXEC,
86 a == ACTION_KEXEC || (a == ACTION_REBOOT && getenv_bool("SYSTEMCTL_SKIP_AUTO_KEXEC") <= 0));
87 SET_FLAG(flags,
88 SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP,
89 a == ACTION_REBOOT && getenv_bool("SYSTEMCTL_SKIP_AUTO_SOFT_REBOOT") <= 0);
90 SET_FLAG(flags, SD_LOGIND_SOFT_REBOOT, a == ACTION_SOFT_REBOOT);
91
92 r = bus_call_method(bus, bus_login_mgr, method_with_flags, &error, NULL, "t", flags);
93 if (r < 0 && FLAGS_SET(flags, SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP) &&
94 sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS)) {
95 sd_bus_error_free(&error);
96 r = bus_call_method(
97 bus,
98 bus_login_mgr,
99 method_with_flags,
100 &error,
101 NULL,
102 "t",
103 flags & ~SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP);
104 }
105 if (r >= 0)
106 return 0;
107 if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) || a == ACTION_SLEEP)
108 return log_error_errno(r, "Call to %s failed: %s", actions[a], bus_error_message(&error, r));
109
110 /* Fall back to original methods in case there is an older version of systemd-logind */
111 log_debug("Method %s not available: %s. Falling back to %s", method_with_flags, bus_error_message(&error, r), actions[a]);
112 sd_bus_error_free(&error);
113
114 r = bus_call_method(bus, bus_login_mgr, actions[a], &error, NULL, "b", arg_ask_password);
115 if (r < 0)
116 return log_error_errno(r, "Call to %s failed: %s", actions[a], bus_error_message(&error, r));
117
118 return 0;
119 #else
120 return -ENOSYS;
121 #endif
122 }
123
124 int logind_check_inhibitors(enum action a) {
125 #if ENABLE_LOGIND
126 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
127 _cleanup_strv_free_ char **sessions = NULL;
128 const char *what, *who, *why, *mode;
129 uint32_t uid, pid;
130 sd_bus *bus;
131 unsigned c = 0;
132 int r;
133
134 assert(a >= 0);
135 assert(a < _ACTION_MAX);
136
137 if (arg_check_inhibitors == 0 || arg_force > 0)
138 return 0;
139
140 if (arg_when > 0)
141 return 0;
142
143 if (arg_check_inhibitors < 0) {
144 if (geteuid() == 0)
145 return 0;
146
147 if (!on_tty())
148 return 0;
149 }
150
151 if (arg_transport != BUS_TRANSPORT_LOCAL)
152 return 0;
153
154 r = acquire_bus(BUS_FULL, &bus);
155 if (r < 0)
156 return r;
157
158 r = bus_call_method(bus, bus_login_mgr, "ListInhibitors", NULL, &reply, NULL);
159 if (r < 0)
160 /* If logind is not around, then there are no inhibitors... */
161 return 0;
162
163 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
164 if (r < 0)
165 return bus_log_parse_error(r);
166
167 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
168 _cleanup_free_ char *comm = NULL, *user = NULL;
169 _cleanup_strv_free_ char **sv = NULL;
170
171 if (!streq(mode, "block"))
172 continue;
173
174 sv = strv_split(what, ":");
175 if (!sv)
176 return log_oom();
177
178 if (!pid_is_valid((pid_t) pid))
179 return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid PID "PID_FMT".", (pid_t) pid);
180
181 if (!strv_contains(sv,
182 IN_SET(a,
183 ACTION_HALT,
184 ACTION_POWEROFF,
185 ACTION_REBOOT,
186 ACTION_KEXEC) ? "shutdown" : "sleep"))
187 continue;
188
189 (void) pid_get_comm(pid, &comm);
190 user = uid_to_name(uid);
191
192 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
193 who, (pid_t) pid, strna(comm), strna(user), why);
194
195 c++;
196 }
197 if (r < 0)
198 return bus_log_parse_error(r);
199
200 r = sd_bus_message_exit_container(reply);
201 if (r < 0)
202 return bus_log_parse_error(r);
203
204 /* Check for current sessions */
205 sd_get_sessions(&sessions);
206 STRV_FOREACH(s, sessions) {
207 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
208
209 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
210 continue;
211
212 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
213 continue;
214
215 if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir"))
216 continue;
217
218 sd_session_get_tty(*s, &tty);
219 sd_session_get_seat(*s, &seat);
220 sd_session_get_service(*s, &service);
221 user = uid_to_name(uid);
222
223 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
224 c++;
225 }
226
227 if (c <= 0)
228 return 0;
229
230 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
231 "Please retry operation after closing inhibitors and logging out other users.\n"
232 "Alternatively, ignore inhibitors and users with 'systemctl %s -i'.",
233 action_table[a].verb);
234 #else
235 return 0;
236 #endif
237 }
238
239 int prepare_firmware_setup(void) {
240
241 if (!arg_firmware_setup)
242 return 0;
243
244 #if ENABLE_LOGIND
245 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
246 sd_bus *bus;
247 int r;
248
249 r = acquire_bus(BUS_FULL, &bus);
250 if (r < 0)
251 return r;
252
253 r = bus_call_method(bus, bus_login_mgr, "SetRebootToFirmwareSetup", &error, NULL, "b", true);
254 if (r < 0)
255 return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
256
257 return 0;
258 #else
259 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
260 "Booting into firmware setup not supported.");
261 #endif
262 }
263
264 int prepare_boot_loader_menu(void) {
265
266 if (arg_boot_loader_menu == USEC_INFINITY)
267 return 0;
268
269 #if ENABLE_LOGIND
270 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
271 sd_bus *bus;
272 int r;
273
274 r = acquire_bus(BUS_FULL, &bus);
275 if (r < 0)
276 return r;
277
278 r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderMenu", &error, NULL, "t", arg_boot_loader_menu);
279 if (r < 0)
280 return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r));
281
282 return 0;
283 #else
284 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
285 "Booting into boot loader menu not supported.");
286 #endif
287 }
288
289 int prepare_boot_loader_entry(void) {
290
291 if (!arg_boot_loader_entry)
292 return 0;
293
294 #if ENABLE_LOGIND
295 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
296 sd_bus *bus;
297 int r;
298
299 r = acquire_bus(BUS_FULL, &bus);
300 if (r < 0)
301 return r;
302
303 r = bus_call_method(bus, bus_login_mgr, "SetRebootToBootLoaderEntry", &error, NULL, "s", arg_boot_loader_entry);
304 if (r < 0)
305 return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r));
306
307 return 0;
308 #else
309 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
310 "Booting into boot loader entry not supported.");
311 #endif
312 }
313
314 int logind_schedule_shutdown(enum action a) {
315 #if ENABLE_LOGIND
316 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
317 const char *action;
318 sd_bus *bus;
319 int r;
320
321 assert(a >= 0);
322 assert(a < _ACTION_MAX);
323
324 r = acquire_bus(BUS_FULL, &bus);
325 if (r < 0)
326 return r;
327
328 action = action_table[a].verb;
329 if (!action)
330 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Scheduling not supported for this action.");
331
332 if (arg_dry_run)
333 action = strjoina("dry-", action);
334
335 (void) logind_set_wall_message(bus);
336
337 r = bus_call_method(bus, bus_login_mgr, "ScheduleShutdown", &error, NULL, "st", action, arg_when);
338 if (r < 0)
339 return log_warning_errno(r, "Failed to schedule shutdown: %s", bus_error_message(&error, r));
340
341 if (!arg_quiet)
342 logind_show_shutdown();
343
344 return 0;
345 #else
346 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
347 "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
348 #endif
349 }
350
351 int logind_cancel_shutdown(void) {
352 #if ENABLE_LOGIND
353 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
354 sd_bus *bus;
355 int r;
356
357 r = acquire_bus(BUS_FULL, &bus);
358 if (r < 0)
359 return r;
360
361 (void) logind_set_wall_message(bus);
362
363 r = bus_call_method(bus, bus_login_mgr, "CancelScheduledShutdown", &error, NULL, NULL);
364 if (r < 0)
365 return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
366
367 return 0;
368 #else
369 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
370 "Not compiled with logind support, cannot cancel scheduled shutdowns.");
371 #endif
372 }
373
374 int logind_show_shutdown(void) {
375 #if ENABLE_LOGIND
376 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
377 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
378 sd_bus *bus;
379 const char *action, *pretty_action;
380 uint64_t elapse;
381 int r;
382
383 r = acquire_bus(BUS_FULL, &bus);
384 if (r < 0)
385 return r;
386
387 r = bus_get_property(bus, bus_login_mgr, "ScheduledShutdown", &error, &reply, "(st)");
388 if (r < 0)
389 return log_error_errno(r, "Failed to query scheduled shutdown: %s", bus_error_message(&error, r));
390
391 r = sd_bus_message_read(reply, "(st)", &action, &elapse);
392 if (r < 0)
393 return r;
394
395 if (isempty(action))
396 return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No scheduled shutdown.");
397
398 if (STR_IN_SET(action, "halt", "poweroff", "exit"))
399 pretty_action = "Shutdown";
400 else if (streq(action, "kexec"))
401 pretty_action = "Reboot via kexec";
402 else if (streq(action, "reboot"))
403 pretty_action = "Reboot";
404 else /* If we don't recognize the action string, we'll show it as-is */
405 pretty_action = action;
406
407 if (arg_action == ACTION_SYSTEMCTL)
408 log_info("%s scheduled for %s, use 'systemctl %s --when=cancel' to cancel.",
409 pretty_action,
410 FORMAT_TIMESTAMP_STYLE(elapse, arg_timestamp_style),
411 action);
412 else
413 log_info("%s scheduled for %s, use 'shutdown -c' to cancel.",
414 pretty_action,
415 FORMAT_TIMESTAMP_STYLE(elapse, arg_timestamp_style));
416
417 return 0;
418 #else
419 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
420 "Not compiled with logind support, cannot show scheduled shutdowns.");
421 #endif
422 }
423
424 int help_boot_loader_entry(void) {
425 #if ENABLE_LOGIND
426 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
427 _cleanup_strv_free_ char **l = NULL;
428 sd_bus *bus;
429 int r;
430
431 r = acquire_bus(BUS_FULL, &bus);
432 if (r < 0)
433 return r;
434
435 r = bus_get_property_strv(bus, bus_login_mgr, "BootLoaderEntries", &error, &l);
436 if (r < 0)
437 return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r));
438
439 if (strv_isempty(l))
440 return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No boot loader entries discovered.");
441
442 STRV_FOREACH(i, l)
443 puts(*i);
444
445 return 0;
446 #else
447 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS),
448 "Not compiled with logind support, cannot display boot loader entries.");
449 #endif
450 }