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",
56 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
62 assert(a
< _ACTION_MAX
);
67 r
= acquire_bus(BUS_FULL
, &bus
);
71 polkit_agent_open_maybe();
72 (void) logind_set_wall_message(bus
);
74 const char *method_with_flags
= strjoina(actions
[a
], "WithFlags");
76 log_debug("%s org.freedesktop.login1.Manager %s dbus call.",
77 arg_dry_run
? "Would execute" : "Executing", method_with_flags
);
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 SET_FLAG(flags
, SD_LOGIND_SOFT_REBOOT
, a
== ACTION_SOFT_REBOOT
);
86 r
= bus_call_method(bus
, bus_login_mgr
, method_with_flags
, &error
, NULL
, "t", flags
);
89 if (!sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
))
90 return log_error_errno(r
, "Call to %s failed: %s", actions
[a
], bus_error_message(&error
, r
));
92 /* Fall back to original methods in case there is an older version of systemd-logind */
93 log_debug("Method %s not available: %s. Falling back to %s", method_with_flags
, bus_error_message(&error
, r
), actions
[a
]);
94 sd_bus_error_free(&error
);
96 r
= bus_call_method(bus
, bus_login_mgr
, actions
[a
], &error
, NULL
, "b", arg_ask_password
);
98 return log_error_errno(r
, "Call to %s failed: %s", actions
[a
], bus_error_message(&error
, r
));
106 int logind_check_inhibitors(enum action a
) {
108 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
109 _cleanup_strv_free_
char **sessions
= NULL
;
110 const char *what
, *who
, *why
, *mode
;
117 assert(a
< _ACTION_MAX
);
119 if (arg_check_inhibitors
== 0 || arg_force
> 0)
125 if (arg_check_inhibitors
< 0) {
133 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
136 r
= acquire_bus(BUS_FULL
, &bus
);
140 r
= bus_call_method(bus
, bus_login_mgr
, "ListInhibitors", NULL
, &reply
, NULL
);
142 /* If logind is not around, then there are no inhibitors... */
145 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
147 return bus_log_parse_error(r
);
149 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
150 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
151 _cleanup_strv_free_
char **sv
= NULL
;
153 if (!streq(mode
, "block"))
156 sv
= strv_split(what
, ":");
160 if (!pid_is_valid((pid_t
) pid
))
161 return log_error_errno(SYNTHETIC_ERRNO(ERANGE
), "Invalid PID "PID_FMT
".", (pid_t
) pid
);
163 if (!strv_contains(sv
,
168 ACTION_KEXEC
) ? "shutdown" : "sleep"))
171 (void) get_process_comm(pid
, &comm
);
172 user
= uid_to_name(uid
);
174 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
175 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
180 return bus_log_parse_error(r
);
182 r
= sd_bus_message_exit_container(reply
);
184 return bus_log_parse_error(r
);
186 /* Check for current sessions */
187 sd_get_sessions(&sessions
);
188 STRV_FOREACH(s
, sessions
) {
189 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
191 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
194 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
197 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
200 sd_session_get_tty(*s
, &tty
);
201 sd_session_get_seat(*s
, &seat
);
202 sd_session_get_service(*s
, &service
);
203 user
= uid_to_name(uid
);
205 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
212 return log_error_errno(SYNTHETIC_ERRNO(EPERM
),
213 "Please retry operation after closing inhibitors and logging out other users.\n"
214 "Alternatively, ignore inhibitors and users with 'systemctl %s -i'.",
215 action_table
[a
].verb
);
221 int prepare_firmware_setup(void) {
223 if (!arg_firmware_setup
)
227 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
231 r
= acquire_bus(BUS_FULL
, &bus
);
235 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToFirmwareSetup", &error
, NULL
, "b", true);
237 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
241 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
242 "Booting into firmware setup not supported.");
246 int prepare_boot_loader_menu(void) {
248 if (arg_boot_loader_menu
== USEC_INFINITY
)
252 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
256 r
= acquire_bus(BUS_FULL
, &bus
);
260 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderMenu", &error
, NULL
, "t", arg_boot_loader_menu
);
262 return log_error_errno(r
, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error
, r
));
266 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
267 "Booting into boot loader menu not supported.");
271 int prepare_boot_loader_entry(void) {
273 if (!arg_boot_loader_entry
)
277 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
281 r
= acquire_bus(BUS_FULL
, &bus
);
285 r
= bus_call_method(bus
, bus_login_mgr
, "SetRebootToBootLoaderEntry", &error
, NULL
, "s", arg_boot_loader_entry
);
287 return log_error_errno(r
, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry
, bus_error_message(&error
, r
));
291 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
292 "Booting into boot loader entry not supported.");
296 int logind_schedule_shutdown(enum action a
) {
298 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
304 assert(a
< _ACTION_MAX
);
306 r
= acquire_bus(BUS_FULL
, &bus
);
310 action
= action_table
[a
].verb
;
312 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Scheduling not supported for this action.");
315 action
= strjoina("dry-", action
);
317 (void) logind_set_wall_message(bus
);
319 r
= bus_call_method(bus
, bus_login_mgr
, "ScheduleShutdown", &error
, NULL
, "st", action
, arg_when
);
321 return log_warning_errno(r
, "Failed to schedule shutdown: %s", bus_error_message(&error
, r
));
324 logind_show_shutdown();
328 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
329 "Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
333 int logind_cancel_shutdown(void) {
335 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
339 r
= acquire_bus(BUS_FULL
, &bus
);
343 (void) logind_set_wall_message(bus
);
345 r
= bus_call_method(bus
, bus_login_mgr
, "CancelScheduledShutdown", &error
, NULL
, NULL
);
347 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
351 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
352 "Not compiled with logind support, cannot cancel scheduled shutdowns.");
356 int logind_show_shutdown(void) {
358 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
359 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
361 const char *action
, *pretty_action
;
365 r
= acquire_bus(BUS_FULL
, &bus
);
369 r
= bus_get_property(bus
, bus_login_mgr
, "ScheduledShutdown", &error
, &reply
, "(st)");
371 return log_error_errno(r
, "Failed to query scheduled shutdown: %s", bus_error_message(&error
, r
));
373 r
= sd_bus_message_read(reply
, "(st)", &action
, &elapse
);
378 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
), "No scheduled shutdown.");
380 if (STR_IN_SET(action
, "halt", "poweroff", "exit"))
381 pretty_action
= "Shutdown";
382 else if (streq(action
, "kexec"))
383 pretty_action
= "Reboot via kexec";
384 else if (streq(action
, "reboot"))
385 pretty_action
= "Reboot";
386 else /* If we don't recognize the action string, we'll show it as-is */
387 pretty_action
= action
;
389 if (arg_action
== ACTION_SYSTEMCTL
)
390 log_info("%s scheduled for %s, use 'systemctl %s --when=cancel' to cancel.",
392 FORMAT_TIMESTAMP_STYLE(elapse
, arg_timestamp_style
),
395 log_info("%s scheduled for %s, use 'shutdown -c' to cancel.",
397 FORMAT_TIMESTAMP_STYLE(elapse
, arg_timestamp_style
));
401 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
402 "Not compiled with logind support, cannot show scheduled shutdowns.");
406 int help_boot_loader_entry(void) {
408 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
409 _cleanup_strv_free_
char **l
= NULL
;
413 r
= acquire_bus(BUS_FULL
, &bus
);
417 r
= bus_get_property_strv(bus
, bus_login_mgr
, "BootLoaderEntries", &error
, &l
);
419 return log_error_errno(r
, "Failed to enumerate boot loader entries: %s", bus_error_message(&error
, r
));
422 return log_error_errno(SYNTHETIC_ERRNO(ENODATA
), "No boot loader entries discovered.");
429 return log_error_errno(SYNTHETIC_ERRNO(ENOSYS
),
430 "Not compiled with logind support, cannot display boot loader entries.");