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 int logind_set_wall_message(void) {
20 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
22 _cleanup_free_
char *m
= NULL
;
25 r
= acquire_bus(BUS_FULL
, &bus
);
29 m
= strv_join(arg_wall
, " ");
33 log_debug("%s wall message \"%s\".", arg_dry_run
? "Would set" : "Setting", m
);
37 r
= bus_call_method(bus
, bus_login_mgr
, "SetWallMessage", &error
, NULL
, "sb", m
, !arg_no_wall
);
39 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
44 /* Ask systemd-logind, which might grant access to unprivileged users through polkit */
45 int logind_reboot(enum action a
) {
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" },
61 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
62 const char *method_with_flags
;
67 if (a
< 0 || a
>= _ACTION_MAX
|| !actions
[a
].method
)
70 r
= acquire_bus(BUS_FULL
, &bus
);
74 polkit_agent_open_maybe();
75 (void) logind_set_wall_message();
77 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run
? "Would execute" : "Executing", actions
[a
].method
);
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
);
85 method_with_flags
= strjoina(actions
[a
].method
, "WithFlags");
87 r
= bus_call_method(bus
, bus_login_mgr
, method_with_flags
, &error
, NULL
, "t", flags
);
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
));
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
);
97 r
= bus_call_method(bus
, bus_login_mgr
, actions
[a
].method
, &error
, NULL
, "b", arg_ask_password
);
99 return log_error_errno(r
, "Failed to %s via logind: %s", actions
[a
].description
, bus_error_message(&error
, r
));
107 int logind_check_inhibitors(enum action a
) {
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
;
118 if (arg_check_inhibitors
== 0 || arg_force
> 0)
124 if (arg_check_inhibitors
< 0) {
132 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
135 r
= acquire_bus(BUS_FULL
, &bus
);
139 r
= bus_call_method(bus
, bus_login_mgr
, "ListInhibitors", NULL
, &reply
, NULL
);
141 /* If logind is not around, then there are no inhibitors... */
144 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
146 return bus_log_parse_error(r
);
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
;
152 if (!streq(mode
, "block"))
155 sv
= strv_split(what
, ":");
159 if (!pid_is_valid((pid_t
) pid
))
160 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
), "Invalid PID "PID_FMT
".", (pid_t
) pid
);
162 if (!strv_contains(sv
,
167 ACTION_KEXEC
) ? "shutdown" : "sleep"))
170 (void) get_process_comm(pid
, &comm
);
171 user
= uid_to_name(uid
);
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
);
179 return bus_log_parse_error(r
);
181 r
= sd_bus_message_exit_container(reply
);
183 return bus_log_parse_error(r
);
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
;
190 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
193 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
196 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
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
);
204 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
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
);
220 int prepare_firmware_setup(void) {
222 if (!arg_firmware_setup
)
226 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
230 r
= acquire_bus(BUS_FULL
, &bus
);
234 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToFirmwareSetup", &error
, NULL
, "b", true);
236 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
240 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
241 "Booting into firmware setup not supported.");
245 int prepare_boot_loader_menu(void) {
247 if (arg_boot_loader_menu
== USEC_INFINITY
)
251 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
255 r
= acquire_bus(BUS_FULL
, &bus
);
259 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderMenu", &error
, NULL
, "t", arg_boot_loader_menu
);
261 return log_error_errno(r
, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error
, r
));
265 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
266 "Booting into boot loader menu not supported.");
270 int prepare_boot_loader_entry(void) {
272 if (!arg_boot_loader_entry
)
276 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
280 r
= acquire_bus(BUS_FULL
, &bus
);
284 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderEntry", &error
, NULL
, "s", arg_boot_loader_entry
);
286 return log_error_errno(r
, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry
, bus_error_message(&error
, r
));
290 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
291 "Booting into boot loader entry not supported.");
295 int logind_schedule_shutdown(void) {
298 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
303 r
= acquire_bus(BUS_FULL
, &bus
);
307 switch (arg_action
) {
311 case ACTION_POWEROFF
:
327 action
= strjoina("dry-", action
);
329 (void) logind_set_wall_message();
331 r
= bus_call_method(bus
, bus_login_mgr
, "ScheduleShutdown", &error
, NULL
, "st", action
, arg_when
);
333 return log_warning_errno(r
, "Failed to schedule shutdown: %s", bus_error_message(&error
, r
));
336 logind_show_shutdown();
340 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
341 "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
345 int logind_cancel_shutdown(void) {
347 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
351 r
= acquire_bus(BUS_FULL
, &bus
);
355 (void) logind_set_wall_message();
357 r
= bus_call_method(bus
, bus_login_mgr
, "CancelScheduledShutdown", &error
, NULL
, NULL
);
359 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
363 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
364 "Not compiled with logind support, cannot cancel scheduled shutdowns.");
368 int logind_show_shutdown(void) {
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
;
373 const char *action
= NULL
;
377 r
= acquire_bus(BUS_FULL
, &bus
);
381 r
= bus_get_property(bus
, bus_login_mgr
, "ScheduledShutdown", &error
, &reply
, "(st)");
383 return log_error_errno(r
, "Failed to query scheduled shutdown: %s", bus_error_message(&error
, r
));
385 r
= sd_bus_message_read(reply
, "(st)", &action
, &elapse
);
390 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
), "No scheduled shutdown.");
392 if (STR_IN_SET(action
, "halt", "poweroff", "exit"))
394 else if (streq(action
, "kexec"))
395 action
= "Reboot via kexec";
396 else if (streq(action
, "reboot"))
399 /* If we don't recognize the action string, we'll show it as-is */
401 log_info("%s scheduled for %s, use 'shutdown -c' to cancel.",
403 FORMAT_TIMESTAMP_STYLE(elapse
, arg_timestamp_style
));
407 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
408 "Not compiled with logind support, cannot show scheduled shutdowns.");
412 int help_boot_loader_entry(void) {
414 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
415 _cleanup_strv_free_
char **l
= NULL
;
420 r
= acquire_bus(BUS_FULL
, &bus
);
424 r
= bus_get_property_strv(bus
, bus_login_mgr
, "BootLoaderEntries", &error
, &l
);
426 return log_error_errno(r
, "Failed to enumerate boot loader entries: %s", bus_error_message(&error
, r
));
429 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
), "No boot loader entries discovered.");
436 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
437 "Not compiled with logind support, cannot display boot loader entries.");