1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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"
18 static int logind_set_wall_message(sd_bus
*bus
) {
20 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
21 _cleanup_free_
char *m
= NULL
;
26 m
= strv_join(arg_wall
, " ");
30 log_debug("%s wall message \"%s\".", arg_dry_run
? "Would set" : "Setting", m
);
34 r
= bus_call_method(bus
, bus_login_mgr
, "SetWallMessage", &error
, NULL
, "sb", m
, !arg_no_wall
);
36 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
41 /* Ask systemd-logind, which might grant access to unprivileged users through polkit */
42 int logind_reboot(enum action a
) {
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",
57 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
63 assert(a
< _ACTION_MAX
);
68 r
= acquire_bus(BUS_FULL
, &bus
);
72 polkit_agent_open_maybe();
73 (void) logind_set_wall_message(bus
);
75 const char *method_with_flags
= a
== ACTION_SLEEP
? actions
[a
] : strjoina(actions
[a
], "WithFlags");
77 log_debug("%s org.freedesktop.login1.Manager %s dbus call.",
78 arg_dry_run
? "Would execute" : "Executing", method_with_flags
);
83 SET_FLAG(flags
, SD_LOGIND_ROOT_CHECK_INHIBITORS
, arg_check_inhibitors
> 0);
85 SD_LOGIND_REBOOT_VIA_KEXEC
,
86 a
== ACTION_KEXEC
|| (a
== ACTION_REBOOT
&& getenv_bool("SYSTEMCTL_SKIP_AUTO_KEXEC") <= 0));
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
);
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
);
103 flags
& ~SD_LOGIND_SOFT_REBOOT_IF_NEXTROOT_SET_UP
);
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
));
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
);
114 r
= bus_call_method(bus
, bus_login_mgr
, actions
[a
], &error
, NULL
, "b", arg_ask_password
);
116 return log_error_errno(r
, "Call to %s failed: %s", actions
[a
], bus_error_message(&error
, r
));
124 int logind_check_inhibitors(enum action a
) {
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
;
135 assert(a
< _ACTION_MAX
);
137 if (arg_check_inhibitors
== 0 || arg_force
> 0)
143 if (arg_check_inhibitors
< 0) {
151 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
154 r
= acquire_bus(BUS_FULL
, &bus
);
158 r
= bus_call_method(bus
, bus_login_mgr
, "ListInhibitors", NULL
, &reply
, NULL
);
160 /* If logind is not around, then there are no inhibitors... */
163 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
165 return bus_log_parse_error(r
);
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
;
171 if (!streq(mode
, "block"))
174 sv
= strv_split(what
, ":");
178 if (!pid_is_valid((pid_t
) pid
))
179 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
), "Invalid PID "PID_FMT
".", (pid_t
) pid
);
181 if (!strv_contains(sv
,
186 ACTION_KEXEC
) ? "shutdown" : "sleep"))
189 (void) pid_get_comm(pid
, &comm
);
190 user
= uid_to_name(uid
);
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
);
198 return bus_log_parse_error(r
);
200 r
= sd_bus_message_exit_container(reply
);
202 return bus_log_parse_error(r
);
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
;
209 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
212 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
215 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
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
);
223 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
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
);
239 int prepare_firmware_setup(void) {
241 if (!arg_firmware_setup
)
245 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
249 r
= acquire_bus(BUS_FULL
, &bus
);
253 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToFirmwareSetup", &error
, NULL
, "b", true);
255 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
259 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
260 "Booting into firmware setup not supported.");
264 int prepare_boot_loader_menu(void) {
266 if (arg_boot_loader_menu
== USEC_INFINITY
)
270 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
274 r
= acquire_bus(BUS_FULL
, &bus
);
278 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderMenu", &error
, NULL
, "t", arg_boot_loader_menu
);
280 return log_error_errno(r
, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error
, r
));
284 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
285 "Booting into boot loader menu not supported.");
289 int prepare_boot_loader_entry(void) {
291 if (!arg_boot_loader_entry
)
295 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
299 r
= acquire_bus(BUS_FULL
, &bus
);
303 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderEntry", &error
, NULL
, "s", arg_boot_loader_entry
);
305 return log_error_errno(r
, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry
, bus_error_message(&error
, r
));
309 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
310 "Booting into boot loader entry not supported.");
314 int logind_schedule_shutdown(enum action a
) {
316 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
322 assert(a
< _ACTION_MAX
);
324 r
= acquire_bus(BUS_FULL
, &bus
);
328 action
= action_table
[a
].verb
;
330 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Scheduling not supported for this action.");
333 action
= strjoina("dry-", action
);
335 (void) logind_set_wall_message(bus
);
337 r
= bus_call_method(bus
, bus_login_mgr
, "ScheduleShutdown", &error
, NULL
, "st", action
, arg_when
);
339 return log_warning_errno(r
, "Failed to schedule shutdown: %s", bus_error_message(&error
, r
));
342 logind_show_shutdown();
346 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
347 "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
351 int logind_cancel_shutdown(void) {
353 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
357 r
= acquire_bus(BUS_FULL
, &bus
);
361 (void) logind_set_wall_message(bus
);
363 r
= bus_call_method(bus
, bus_login_mgr
, "CancelScheduledShutdown", &error
, NULL
, NULL
);
365 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
369 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
370 "Not compiled with logind support, cannot cancel scheduled shutdowns.");
374 int logind_show_shutdown(void) {
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
;
379 const char *action
, *pretty_action
;
383 r
= acquire_bus(BUS_FULL
, &bus
);
387 r
= bus_get_property(bus
, bus_login_mgr
, "ScheduledShutdown", &error
, &reply
, "(st)");
389 return log_error_errno(r
, "Failed to query scheduled shutdown: %s", bus_error_message(&error
, r
));
391 r
= sd_bus_message_read(reply
, "(st)", &action
, &elapse
);
396 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
), "No scheduled shutdown.");
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
;
407 if (arg_action
== ACTION_SYSTEMCTL
)
408 log_info("%s scheduled for %s, use 'systemctl %s --when=cancel' to cancel.",
410 FORMAT_TIMESTAMP_STYLE(elapse
, arg_timestamp_style
),
413 log_info("%s scheduled for %s, use 'shutdown -c' to cancel.",
415 FORMAT_TIMESTAMP_STYLE(elapse
, arg_timestamp_style
));
419 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
420 "Not compiled with logind support, cannot show scheduled shutdowns.");
424 int help_boot_loader_entry(void) {
426 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
427 _cleanup_strv_free_
char **l
= NULL
;
431 r
= acquire_bus(BUS_FULL
, &bus
);
435 r
= bus_get_property_strv(bus
, bus_login_mgr
, "BootLoaderEntries", &error
, &l
);
437 return log_error_errno(r
, "Failed to enumerate boot loader entries: %s", bus_error_message(&error
, r
));
440 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
), "No boot loader entries discovered.");
447 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
448 "Not compiled with logind support, cannot display boot loader entries.");