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