1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "bus-locator.h"
9 #include "process-util.h"
10 #include "systemctl-logind.h"
11 #include "systemctl-start-unit.h"
12 #include "systemctl-util.h"
13 #include "systemctl.h"
14 #include "terminal-util.h"
15 #include "user-util.h"
17 int logind_set_wall_message(void) {
19 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
21 _cleanup_free_
char *m
= NULL
;
24 r
= acquire_bus(BUS_FULL
, &bus
);
28 m
= strv_join(arg_wall
, " ");
32 log_debug("%s wall message \"%s\".", arg_dry_run
? "Would set" : "Setting", m
);
36 r
= bus_call_method(bus
, bus_login_mgr
, "SetWallMessage", &error
, NULL
, "sb", m
, !arg_no_wall
);
38 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
43 /* Ask systemd-logind, which might grant access to unprivileged users through polkit */
44 int logind_reboot(enum action a
) {
48 const char *description
;
49 } actions
[_ACTION_MAX
] = {
50 [ACTION_POWEROFF
] = { "PowerOff", "power off system" },
51 [ACTION_REBOOT
] = { "Reboot", "reboot system" },
52 [ACTION_HALT
] = { "Halt", "halt system" },
53 [ACTION_SUSPEND
] = { "Suspend", "suspend system" },
54 [ACTION_HIBERNATE
] = { "Hibernate", "hibernate system" },
55 [ACTION_HYBRID_SLEEP
] = { "HybridSleep", "put system into hybrid sleep" },
56 [ACTION_SUSPEND_THEN_HIBERNATE
] = { "SuspendThenHibernate", "suspend system, hibernate later" },
59 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
63 if (a
< 0 || a
>= _ACTION_MAX
|| !actions
[a
].method
)
66 r
= acquire_bus(BUS_FULL
, &bus
);
70 polkit_agent_open_maybe();
71 (void) logind_set_wall_message();
73 log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run
? "Would execute" : "Executing", actions
[a
].method
);
78 r
= bus_call_method(bus
, bus_login_mgr
, actions
[a
].method
, &error
, NULL
, "b", arg_ask_password
);
80 return log_error_errno(r
, "Failed to %s via logind: %s", actions
[a
].description
, bus_error_message(&error
, r
));
88 int logind_check_inhibitors(enum action a
) {
90 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
91 _cleanup_strv_free_
char **sessions
= NULL
;
92 const char *what
, *who
, *why
, *mode
;
99 if (arg_ignore_inhibitors
|| arg_force
> 0)
111 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
114 r
= acquire_bus(BUS_FULL
, &bus
);
118 r
= bus_call_method(bus
, bus_login_mgr
, "ListInhibitors", NULL
, &reply
, NULL
);
120 /* If logind is not around, then there are no inhibitors... */
123 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
125 return bus_log_parse_error(r
);
127 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
128 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
129 _cleanup_strv_free_
char **sv
= NULL
;
131 if (!streq(mode
, "block"))
134 sv
= strv_split(what
, ":");
138 if (!pid_is_valid((pid_t
) pid
))
139 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
), "Invalid PID "PID_FMT
".", (pid_t
) pid
);
141 if (!strv_contains(sv
,
146 ACTION_KEXEC
) ? "shutdown" : "sleep"))
149 get_process_comm(pid
, &comm
);
150 user
= uid_to_name(uid
);
152 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
153 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
158 return bus_log_parse_error(r
);
160 r
= sd_bus_message_exit_container(reply
);
162 return bus_log_parse_error(r
);
164 /* Check for current sessions */
165 sd_get_sessions(&sessions
);
166 STRV_FOREACH(s
, sessions
) {
167 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
169 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
172 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
175 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
178 sd_session_get_tty(*s
, &tty
);
179 sd_session_get_seat(*s
, &seat
);
180 sd_session_get_service(*s
, &service
);
181 user
= uid_to_name(uid
);
183 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
190 return log_error_errno(SYNTHETIC_ERRNO(EPERM
),
191 "Please retry operation after closing inhibitors and logging out other users.\n"
192 "Alternatively, ignore inhibitors and users with 'systemctl %s -i'.",
193 action_table
[a
].verb
);
199 int prepare_firmware_setup(void) {
201 if (!arg_firmware_setup
)
205 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
209 r
= acquire_bus(BUS_FULL
, &bus
);
213 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToFirmwareSetup", &error
, NULL
, "b", true);
215 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
219 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
220 "Booting into firmware setup not supported.");
224 int prepare_boot_loader_menu(void) {
226 if (arg_boot_loader_menu
== USEC_INFINITY
)
230 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
234 r
= acquire_bus(BUS_FULL
, &bus
);
238 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderMenu", &error
, NULL
, "t", arg_boot_loader_menu
);
240 return log_error_errno(r
, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error
, r
));
244 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
245 "Booting into boot loader menu not supported.");
249 int prepare_boot_loader_entry(void) {
251 if (!arg_boot_loader_entry
)
255 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
259 r
= acquire_bus(BUS_FULL
, &bus
);
263 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderEntry", &error
, NULL
, "s", arg_boot_loader_entry
);
265 return log_error_errno(r
, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry
, bus_error_message(&error
, r
));
269 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
270 "Booting into boot loader entry not supported.");
274 int logind_schedule_shutdown(void) {
277 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
278 char date
[FORMAT_TIMESTAMP_MAX
];
280 const char *log_action
;
284 r
= acquire_bus(BUS_FULL
, &bus
);
288 switch (arg_action
) {
291 log_action
= "Shutdown";
293 case ACTION_POWEROFF
:
295 log_action
= "Shutdown";
299 log_action
= "Reboot via kexec";
303 log_action
= "Shutdown";
308 log_action
= "Reboot";
313 action
= strjoina("dry-", action
);
315 (void) logind_set_wall_message();
317 r
= bus_call_method(bus
, bus_login_mgr
, "ScheduleShutdown", &error
, NULL
, "st", action
, arg_when
);
319 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
322 log_info("%s scheduled for %s, use 'shutdown -c' to cancel.", log_action
, format_timestamp_style(date
, sizeof(date
), arg_when
, arg_timestamp_style
));
325 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
326 "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
330 int logind_cancel_shutdown(void) {
332 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
336 r
= acquire_bus(BUS_FULL
, &bus
);
340 (void) logind_set_wall_message();
342 r
= bus_call_method(bus
, bus_login_mgr
, "CancelScheduledShutdown", &error
, NULL
, NULL
);
344 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
348 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
349 "Not compiled with logind support, cannot cancel scheduled shutdowns.");
353 int help_boot_loader_entry(void) {
355 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
356 _cleanup_strv_free_
char **l
= NULL
;
361 r
= acquire_bus(BUS_FULL
, &bus
);
365 r
= bus_get_property_strv(bus
, bus_login_mgr
, "BootLoaderEntries", &error
, &l
);
367 return log_error_errno(r
, "Failed to enumerate boot loader entries: %s", bus_error_message(&error
, r
));
370 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
), "No boot loader entries discovered.");
377 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
378 "Not compiled with logind support, cannot display boot loader entries.");