1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "sd-messages.h"
30 #include "path-util.h"
32 #include "sleep-config.h"
33 #include "fileio-label.h"
34 #include "unit-name.h"
37 #include "bus-error.h"
38 #include "bus-common-errors.h"
39 #include "udev-util.h"
40 #include "selinux-util.h"
43 #include "formats-util.h"
44 #include "process-util.h"
45 #include "terminal-util.h"
46 #include "utmp-wtmp.h"
48 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
49 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
58 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
62 r = sd_bus_creds_get_session(creds, &name);
67 session = hashmap_get(m->sessions, name);
69 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
75 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
83 if (uid == UID_INVALID) {
84 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
86 /* Note that we get the owner UID of the session, not the actual client UID here! */
87 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
91 r = sd_bus_creds_get_owner_uid(creds, &uid);
96 user = hashmap_get(m->users, UID_TO_PTR(uid));
98 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
104 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
115 r = manager_get_session_from_creds(m, message, NULL, error, &session);
119 seat = session->seat;
122 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
124 seat = hashmap_get(m->seats, name);
126 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
133 static int property_get_idle_hint(
136 const char *interface,
137 const char *property,
138 sd_bus_message *reply,
140 sd_bus_error *error) {
142 Manager *m = userdata;
148 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
151 static int property_get_idle_since_hint(
154 const char *interface,
155 const char *property,
156 sd_bus_message *reply,
158 sd_bus_error *error) {
160 Manager *m = userdata;
161 dual_timestamp t = DUAL_TIMESTAMP_NULL;
167 manager_get_idle_hint(m, &t);
169 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
172 static int property_get_inhibited(
175 const char *interface,
176 const char *property,
177 sd_bus_message *reply,
179 sd_bus_error *error) {
181 Manager *m = userdata;
188 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
190 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
193 static int property_get_preparing(
196 const char *interface,
197 const char *property,
198 sd_bus_message *reply,
200 sd_bus_error *error) {
202 Manager *m = userdata;
209 if (streq(property, "PreparingForShutdown"))
210 b = !!(m->action_what & INHIBIT_SHUTDOWN);
212 b = !!(m->action_what & INHIBIT_SLEEP);
214 return sd_bus_message_append(reply, "b", b);
217 static int property_get_scheduled_shutdown(
220 const char *interface,
221 const char *property,
222 sd_bus_message *reply,
224 sd_bus_error *error) {
226 Manager *m = userdata;
233 r = sd_bus_message_open_container(reply, 'r', "st");
237 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
241 return sd_bus_message_close_container(reply);
244 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
246 static int property_get_docked(
249 const char *interface,
250 const char *property,
251 sd_bus_message *reply,
253 sd_bus_error *error) {
255 Manager *m = userdata;
261 return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
264 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
265 _cleanup_free_ char *p = NULL;
266 Manager *m = userdata;
274 r = sd_bus_message_read(message, "s", &name);
278 r = manager_get_session_from_creds(m, message, name, error, &session);
282 p = session_bus_path(session);
286 return sd_bus_reply_method_return(message, "o", p);
289 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
290 _cleanup_free_ char *p = NULL;
291 Session *session = NULL;
292 Manager *m = userdata;
299 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
301 r = sd_bus_message_read(message, "u", &pid);
306 r = manager_get_session_from_creds(m, message, NULL, error, &session);
310 r = manager_get_session_by_pid(m, pid, &session);
315 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
318 p = session_bus_path(session);
322 return sd_bus_reply_method_return(message, "o", p);
325 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
326 _cleanup_free_ char *p = NULL;
327 Manager *m = userdata;
335 r = sd_bus_message_read(message, "u", &uid);
339 r = manager_get_user_from_creds(m, message, uid, error, &user);
343 p = user_bus_path(user);
347 return sd_bus_reply_method_return(message, "o", p);
350 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
351 _cleanup_free_ char *p = NULL;
352 Manager *m = userdata;
360 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
362 r = sd_bus_message_read(message, "u", &pid);
367 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
371 r = manager_get_user_by_pid(m, pid, &user);
375 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
378 p = user_bus_path(user);
382 return sd_bus_reply_method_return(message, "o", p);
385 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
386 _cleanup_free_ char *p = NULL;
387 Manager *m = userdata;
395 r = sd_bus_message_read(message, "s", &name);
399 r = manager_get_seat_from_creds(m, message, name, error, &seat);
403 p = seat_bus_path(seat);
407 return sd_bus_reply_method_return(message, "o", p);
410 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
411 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
412 Manager *m = userdata;
420 r = sd_bus_message_new_method_return(message, &reply);
424 r = sd_bus_message_open_container(reply, 'a', "(susso)");
428 HASHMAP_FOREACH(session, m->sessions, i) {
429 _cleanup_free_ char *p = NULL;
431 p = session_bus_path(session);
435 r = sd_bus_message_append(reply, "(susso)",
437 (uint32_t) session->user->uid,
439 session->seat ? session->seat->id : "",
445 r = sd_bus_message_close_container(reply);
449 return sd_bus_send(NULL, reply, NULL);
452 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
453 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
454 Manager *m = userdata;
462 r = sd_bus_message_new_method_return(message, &reply);
466 r = sd_bus_message_open_container(reply, 'a', "(uso)");
470 HASHMAP_FOREACH(user, m->users, i) {
471 _cleanup_free_ char *p = NULL;
473 p = user_bus_path(user);
477 r = sd_bus_message_append(reply, "(uso)",
478 (uint32_t) user->uid,
485 r = sd_bus_message_close_container(reply);
489 return sd_bus_send(NULL, reply, NULL);
492 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
493 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
494 Manager *m = userdata;
502 r = sd_bus_message_new_method_return(message, &reply);
506 r = sd_bus_message_open_container(reply, 'a', "(so)");
510 HASHMAP_FOREACH(seat, m->seats, i) {
511 _cleanup_free_ char *p = NULL;
513 p = seat_bus_path(seat);
517 r = sd_bus_message_append(reply, "(so)", seat->id, p);
522 r = sd_bus_message_close_container(reply);
526 return sd_bus_send(NULL, reply, NULL);
529 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
530 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
531 Manager *m = userdata;
532 Inhibitor *inhibitor;
539 r = sd_bus_message_new_method_return(message, &reply);
543 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
547 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
549 r = sd_bus_message_append(reply, "(ssssuu)",
550 strempty(inhibit_what_to_string(inhibitor->what)),
551 strempty(inhibitor->who),
552 strempty(inhibitor->why),
553 strempty(inhibit_mode_to_string(inhibitor->mode)),
554 (uint32_t) inhibitor->uid,
555 (uint32_t) inhibitor->pid);
560 r = sd_bus_message_close_container(reply);
564 return sd_bus_send(NULL, reply, NULL);
567 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
568 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
569 uint32_t uid, leader, audit_id = 0;
570 _cleanup_free_ char *id = NULL;
571 Session *session = NULL;
572 Manager *m = userdata;
584 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
589 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
592 t = _SESSION_TYPE_INVALID;
594 t = session_type_from_string(type);
596 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
600 c = _SESSION_CLASS_INVALID;
602 c = session_class_from_string(class);
604 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
607 if (isempty(desktop))
610 if (!string_is_safe(desktop))
611 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
617 seat = hashmap_get(m->seats, cseat);
619 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
622 if (tty_is_vc(tty)) {
627 else if (seat != m->seat0)
628 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
630 v = vtnr_from_tty(tty);
632 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
636 else if (vtnr != (uint32_t) v)
637 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
639 } else if (tty_is_console(tty)) {
643 else if (seat != m->seat0)
644 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
647 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
651 if (seat_has_vts(seat)) {
652 if (!vtnr || vtnr > 63)
653 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
656 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
660 r = sd_bus_message_enter_container(message, 'a', "(sv)");
664 if (t == _SESSION_TYPE_INVALID) {
665 if (!isempty(display))
667 else if (!isempty(tty))
670 t = SESSION_UNSPECIFIED;
673 if (c == _SESSION_CLASS_INVALID) {
674 if (t == SESSION_UNSPECIFIED)
675 c = SESSION_BACKGROUND;
681 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
683 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
687 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
692 r = manager_get_session_by_pid(m, leader, NULL);
694 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
697 * Old gdm and lightdm start the user-session on the same VT as
698 * the greeter session. But they destroy the greeter session
699 * after the user-session and want the user-session to take
700 * over the VT. We need to support this for
701 * backwards-compatibility, so make sure we allow new sessions
702 * on a VT that a greeter is running on.
705 vtnr < m->seat0->position_count &&
706 m->seat0->positions[vtnr] &&
707 m->seat0->positions[vtnr]->class != SESSION_GREETER)
708 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
710 audit_session_from_pid(leader, &audit_id);
712 /* Keep our session IDs and the audit session IDs in sync */
714 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
717 /* Wut? There's already a session by this name and we
718 * didn't find it above? Weird, then let's not trust
719 * the audit data and let's better register a new
721 if (hashmap_get(m->sessions, id)) {
722 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
735 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
738 } while (hashmap_get(m->sessions, id));
741 r = manager_add_user_by_uid(m, uid, &user);
745 r = manager_add_session(m, id, &session);
749 session_set_user(session, user);
751 session->leader = leader;
752 session->audit_id = audit_id;
755 session->remote = remote;
756 session->vtnr = vtnr;
759 session->tty = strdup(tty);
766 if (!isempty(display)) {
767 session->display = strdup(display);
768 if (!session->display) {
774 if (!isempty(remote_user)) {
775 session->remote_user = strdup(remote_user);
776 if (!session->remote_user) {
782 if (!isempty(remote_host)) {
783 session->remote_host = strdup(remote_host);
784 if (!session->remote_host) {
790 if (!isempty(service)) {
791 session->service = strdup(service);
792 if (!session->service) {
798 if (!isempty(desktop)) {
799 session->desktop = strdup(desktop);
800 if (!session->desktop) {
807 r = seat_attach_session(seat, session);
812 r = session_start(session);
816 session->create_message = sd_bus_message_ref(message);
818 /* Now, let's wait until the slice unit and stuff got
819 * created. We send the reply back from
820 * session_send_create_reply(). */
826 session_add_to_gc_queue(session);
829 user_add_to_gc_queue(user);
834 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
835 Manager *m = userdata;
843 r = sd_bus_message_read(message, "s", &name);
847 r = manager_get_session_from_creds(m, message, name, error, &session);
851 r = session_release(session);
855 return sd_bus_reply_method_return(message, NULL);
858 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
859 Manager *m = userdata;
867 r = sd_bus_message_read(message, "s", &name);
871 r = manager_get_session_from_creds(m, message, name, error, &session);
875 return bus_session_method_activate(message, session, error);
878 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
879 const char *session_name, *seat_name;
880 Manager *m = userdata;
888 /* Same as ActivateSession() but refuses to work if
889 * the seat doesn't match */
891 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
895 r = manager_get_session_from_creds(m, message, session_name, error, &session);
899 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
903 if (session->seat != seat)
904 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
906 r = session_activate(session);
910 return sd_bus_reply_method_return(message, NULL);
913 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
914 Manager *m = userdata;
922 r = sd_bus_message_read(message, "s", &name);
926 r = manager_get_session_from_creds(m, message, name, error, &session);
930 return bus_session_method_lock(message, session, error);
933 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
934 Manager *m = userdata;
940 r = bus_verify_polkit_async(
943 "org.freedesktop.login1.lock-sessions",
951 return 1; /* Will call us back */
953 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
957 return sd_bus_reply_method_return(message, NULL);
960 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
962 Manager *m = userdata;
969 r = sd_bus_message_read(message, "s", &name);
973 r = manager_get_session_from_creds(m, message, name, error, &session);
977 return bus_session_method_kill(message, session, error);
980 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
981 Manager *m = userdata;
989 r = sd_bus_message_read(message, "u", &uid);
993 r = manager_get_user_from_creds(m, message, uid, error, &user);
997 return bus_user_method_kill(message, user, error);
1000 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1001 Manager *m = userdata;
1009 r = sd_bus_message_read(message, "s", &name);
1013 r = manager_get_session_from_creds(m, message, name, error, &session);
1017 return bus_session_method_terminate(message, session, error);
1020 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1021 Manager *m = userdata;
1029 r = sd_bus_message_read(message, "u", &uid);
1033 r = manager_get_user_from_creds(m, message, uid, error, &user);
1037 return bus_user_method_terminate(message, user, error);
1040 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1041 Manager *m = userdata;
1049 r = sd_bus_message_read(message, "s", &name);
1053 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1057 return bus_seat_method_terminate(message, seat, error);
1060 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1061 _cleanup_free_ char *cc = NULL;
1062 Manager *m = userdata;
1072 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1076 if (uid == UID_INVALID) {
1077 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1079 /* Note that we get the owner UID of the session, not the actual client UID here! */
1080 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1084 r = sd_bus_creds_get_owner_uid(creds, &uid);
1092 return errno ? -errno : -ENOENT;
1094 r = bus_verify_polkit_async(
1097 "org.freedesktop.login1.set-user-linger",
1100 &m->polkit_registry,
1105 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1107 mkdir_p_label("/var/lib/systemd", 0755);
1109 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1113 cc = cescape(pw->pw_name);
1117 path = strjoina("/var/lib/systemd/linger/", cc);
1125 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1132 if (r < 0 && errno != ENOENT)
1135 u = hashmap_get(m->users, UID_TO_PTR(uid));
1137 user_add_to_gc_queue(u);
1140 return sd_bus_reply_method_return(message, NULL);
1143 static int trigger_device(Manager *m, struct udev_device *d) {
1144 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1145 struct udev_list_entry *first, *item;
1150 e = udev_enumerate_new(m->udev);
1155 r = udev_enumerate_add_match_parent(e, d);
1160 r = udev_enumerate_scan_devices(e);
1164 first = udev_enumerate_get_list_entry(e);
1165 udev_list_entry_foreach(item, first) {
1166 _cleanup_free_ char *t = NULL;
1169 p = udev_list_entry_get_name(item);
1171 t = strappend(p, "/uevent");
1175 write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
1181 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1182 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1183 _cleanup_free_ char *rule = NULL, *file = NULL;
1184 const char *id_for_seat;
1191 d = udev_device_new_from_syspath(m->udev, sysfs);
1195 if (!udev_device_has_tag(d, "seat"))
1198 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1202 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1205 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1208 mkdir_p_label("/etc/udev/rules.d", 0755);
1209 mac_selinux_init("/etc");
1210 r = write_string_file_atomic_label(file, rule);
1214 return trigger_device(m, d);
1217 static int flush_devices(Manager *m) {
1218 _cleanup_closedir_ DIR *d;
1222 d = opendir("/etc/udev/rules.d");
1224 if (errno != ENOENT)
1225 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1229 while ((de = readdir(d))) {
1231 if (!dirent_is_file(de))
1234 if (!startswith(de->d_name, "72-seat-"))
1237 if (!endswith(de->d_name, ".rules"))
1240 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1241 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1245 return trigger_device(m, NULL);
1248 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1249 const char *sysfs, *seat;
1250 Manager *m = userdata;
1256 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1260 if (!path_startswith(sysfs, "/sys"))
1261 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1263 if (!seat_name_is_valid(seat))
1264 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1266 r = bus_verify_polkit_async(
1269 "org.freedesktop.login1.attach-device",
1272 &m->polkit_registry,
1277 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1279 r = attach_device(m, seat, sysfs);
1283 return sd_bus_reply_method_return(message, NULL);
1286 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1287 Manager *m = userdata;
1293 r = sd_bus_message_read(message, "b", &interactive);
1297 r = bus_verify_polkit_async(
1300 "org.freedesktop.login1.flush-devices",
1303 &m->polkit_registry,
1308 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1310 r = flush_devices(m);
1314 return sd_bus_reply_method_return(message, NULL);
1317 static int have_multiple_sessions(
1326 /* Check for other users' sessions. Greeter sessions do not
1327 * count, and non-login sessions do not count either. */
1328 HASHMAP_FOREACH(session, m->sessions, i)
1329 if (session->class == SESSION_USER &&
1330 session->user->uid != uid)
1336 static int bus_manager_log_shutdown(
1339 const char *unit_name) {
1346 if (w != INHIBIT_SHUTDOWN)
1349 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1350 p = "MESSAGE=System is powering down.";
1351 q = "SHUTDOWN=power-off";
1352 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1353 p = "MESSAGE=System is halting.";
1354 q = "SHUTDOWN=halt";
1355 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1356 p = "MESSAGE=System is rebooting.";
1357 q = "SHUTDOWN=reboot";
1358 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1359 p = "MESSAGE=System is rebooting with kexec.";
1360 q = "SHUTDOWN=kexec";
1362 p = "MESSAGE=System is shutting down.";
1366 return log_struct(LOG_NOTICE,
1367 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1373 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1374 Manager *m = userdata;
1379 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1383 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1388 if (until <= now(CLOCK_MONOTONIC))
1391 /* We want to ignore the lid switch for a while after each
1392 * suspend, and after boot-up. Hence let's install a timer for
1393 * this. As long as the event source exists we ignore the lid
1396 if (m->lid_switch_ignore_event_source) {
1399 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1406 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1408 r = sd_event_add_time(
1410 &m->lid_switch_ignore_event_source,
1413 lid_switch_ignore_handler, m);
1418 static int execute_shutdown_or_sleep(
1421 const char *unit_name,
1422 sd_bus_error *error) {
1424 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1431 assert(w < _INHIBIT_WHAT_MAX);
1434 bus_manager_log_shutdown(m, w, unit_name);
1436 r = sd_bus_call_method(
1438 "org.freedesktop.systemd1",
1439 "/org/freedesktop/systemd1",
1440 "org.freedesktop.systemd1.Manager",
1444 "ss", unit_name, "replace-irreversibly");
1448 r = sd_bus_message_read(reply, "o", &p);
1456 m->action_unit = unit_name;
1457 free(m->action_job);
1461 /* Make sure the lid switch is ignored for a while */
1462 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1467 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1469 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1470 Inhibitor *offending = NULL;
1475 if (manager->action_what == 0 || manager->action_job)
1478 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1479 _cleanup_free_ char *comm = NULL, *u = NULL;
1484 (void) get_process_comm(offending->pid, &comm);
1485 u = uid_to_name(offending->uid);
1487 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1488 offending->uid, strna(u),
1489 offending->pid, strna(comm));
1492 /* Actually do the operation */
1493 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1495 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1497 manager->action_unit = NULL;
1498 manager->action_what = 0;
1505 static int manager_inhibit_timeout_handler(
1510 Manager *manager = userdata;
1514 assert(manager->inhibit_timeout_source == s);
1516 r = manager_dispatch_delayed(manager, true);
1517 return (r < 0) ? r : 0;
1520 static int delay_shutdown_or_sleep(
1523 const char *unit_name) {
1530 assert(w < _INHIBIT_WHAT_MAX);
1533 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1535 if (m->inhibit_timeout_source) {
1536 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1538 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1540 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1542 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1544 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1545 timeout_val, 0, manager_inhibit_timeout_handler, m);
1550 m->action_unit = unit_name;
1556 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1558 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1559 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1560 [INHIBIT_SLEEP] = "PrepareForSleep"
1563 int active = _active;
1567 assert(w < _INHIBIT_WHAT_MAX);
1568 assert(signal_name[w]);
1570 return sd_bus_emit_signal(m->bus,
1571 "/org/freedesktop/login1",
1572 "org.freedesktop.login1.Manager",
1578 int bus_manager_shutdown_or_sleep_now_or_later(
1580 const char *unit_name,
1582 sd_bus_error *error) {
1590 assert(w <= _INHIBIT_WHAT_MAX);
1591 assert(!m->action_job);
1593 /* Tell everybody to prepare for shutdown/sleep */
1594 send_prepare_for(m, w, true);
1597 m->inhibit_delay_max > 0 &&
1598 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1601 /* Shutdown is delayed, keep in mind what we
1602 * want to do, and start a timeout */
1603 r = delay_shutdown_or_sleep(m, w, unit_name);
1605 /* Shutdown is not delayed, execute it
1607 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1612 static int verify_shutdown_creds(
1614 sd_bus_message *message,
1618 const char *action_multiple_sessions,
1619 const char *action_ignore_inhibit,
1620 sd_bus_error *error) {
1622 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1623 bool multiple_sessions, blocked;
1630 assert(w <= _INHIBIT_WHAT_MAX);
1632 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1636 r = sd_bus_creds_get_euid(creds, &uid);
1640 r = have_multiple_sessions(m, uid);
1644 multiple_sessions = r > 0;
1645 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1647 if (multiple_sessions && action_multiple_sessions) {
1648 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1652 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1655 if (blocked && action_ignore_inhibit) {
1656 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1660 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1663 if (!multiple_sessions && !blocked && action) {
1664 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1668 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1674 static int method_do_shutdown_or_sleep(
1676 sd_bus_message *message,
1677 const char *unit_name,
1680 const char *action_multiple_sessions,
1681 const char *action_ignore_inhibit,
1682 const char *sleep_verb,
1683 sd_bus_error *error) {
1691 assert(w <= _INHIBIT_WHAT_MAX);
1693 r = sd_bus_message_read(message, "b", &interactive);
1697 /* Don't allow multiple jobs being executed at the same time */
1699 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1702 r = can_sleep(sleep_verb);
1707 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1710 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1711 action_ignore_inhibit, error);
1715 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1719 return sd_bus_reply_method_return(message, NULL);
1722 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1723 Manager *m = userdata;
1725 return method_do_shutdown_or_sleep(
1727 SPECIAL_POWEROFF_TARGET,
1729 "org.freedesktop.login1.power-off",
1730 "org.freedesktop.login1.power-off-multiple-sessions",
1731 "org.freedesktop.login1.power-off-ignore-inhibit",
1736 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1737 Manager *m = userdata;
1739 return method_do_shutdown_or_sleep(
1741 SPECIAL_REBOOT_TARGET,
1743 "org.freedesktop.login1.reboot",
1744 "org.freedesktop.login1.reboot-multiple-sessions",
1745 "org.freedesktop.login1.reboot-ignore-inhibit",
1750 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1751 Manager *m = userdata;
1753 return method_do_shutdown_or_sleep(
1755 SPECIAL_SUSPEND_TARGET,
1757 "org.freedesktop.login1.suspend",
1758 "org.freedesktop.login1.suspend-multiple-sessions",
1759 "org.freedesktop.login1.suspend-ignore-inhibit",
1764 static int nologin_timeout_handler(
1769 Manager *m = userdata;
1772 log_info("Creating /run/nologin, blocking further logins...");
1774 r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_ATOMIC);
1776 log_error_errno(r, "Failed to create /run/nologin: %m");
1778 m->unlink_nologin = true;
1783 static int update_schedule_file(Manager *m) {
1786 _cleanup_fclose_ FILE *f = NULL;
1787 _cleanup_free_ char *t = NULL, *temp_path = NULL;
1791 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1793 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1795 t = cescape(m->wall_message);
1799 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1801 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1803 (void) fchmod(fileno(f), 0644);
1809 m->scheduled_shutdown_timeout,
1810 m->enable_wall_messages,
1811 m->scheduled_shutdown_type);
1813 if (!isempty(m->wall_message))
1814 fprintf(f, "WALL_MESSAGE=%s\n", t);
1816 (void) fflush_and_check(f);
1818 if (ferror(f) || rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1819 log_error_errno(errno, "Failed to write information about scheduled shutdowns: %m");
1822 (void) unlink(temp_path);
1823 (void) unlink("/run/systemd/shutdown/scheduled");
1829 static int manager_scheduled_shutdown_handler(
1834 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1835 Manager *m = userdata;
1841 if (isempty(m->scheduled_shutdown_type))
1844 if (streq(m->scheduled_shutdown_type, "halt"))
1845 target = SPECIAL_HALT_TARGET;
1846 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1847 target = SPECIAL_POWEROFF_TARGET;
1849 target = SPECIAL_REBOOT_TARGET;
1851 r = execute_shutdown_or_sleep(m, 0, target, &error);
1853 return log_error_errno(r, "Unable to execute transition to %s: %m", target);
1858 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1859 Manager *m = userdata;
1860 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1861 const char *action_multiple_sessions = NULL;
1862 const char *action_ignore_inhibit = NULL;
1863 const char *action = NULL;
1871 r = sd_bus_message_read(message, "st", &type, &elapse);
1875 if (streq(type, "reboot")) {
1876 action = "org.freedesktop.login1.reboot";
1877 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1878 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1879 } else if (streq(type, "halt")) {
1880 action = "org.freedesktop.login1.halt";
1881 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1882 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1883 } else if (streq(type, "poweroff")) {
1884 action = "org.freedesktop.login1.poweroff";
1885 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1886 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1888 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1890 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1891 action, action_multiple_sessions, action_ignore_inhibit, error);
1895 if (m->scheduled_shutdown_timeout_source) {
1896 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1898 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1900 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
1902 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1904 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
1905 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
1907 return log_error_errno(r, "sd_event_add_time() failed: %m");
1910 r = free_and_strdup(&m->scheduled_shutdown_type, type);
1912 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1916 if (m->nologin_timeout_source) {
1917 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
1919 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1921 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
1923 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1925 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
1926 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
1928 return log_error_errno(r, "sd_event_add_time() failed: %m");
1931 m->scheduled_shutdown_timeout = elapse;
1933 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1937 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
1938 (void) sd_bus_creds_get_tty(creds, &tty);
1940 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
1942 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1947 r = manager_setup_wall_message_timer(m);
1951 if (!isempty(type)) {
1952 r = update_schedule_file(m);
1956 (void) unlink("/run/systemd/shutdown/scheduled");
1958 return sd_bus_reply_method_return(message, NULL);
1961 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1962 Manager *m = userdata;
1968 cancelled = m->scheduled_shutdown_type != NULL;
1970 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1971 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
1972 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
1973 free(m->scheduled_shutdown_type);
1974 m->scheduled_shutdown_type = NULL;
1975 m->scheduled_shutdown_timeout = 0;
1977 if (m->unlink_nologin) {
1978 (void) unlink("/run/nologin");
1979 m->unlink_nologin = false;
1983 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1984 const char *tty = NULL;
1988 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1990 (void) sd_bus_creds_get_uid(creds, &uid);
1991 (void) sd_bus_creds_get_tty(creds, &tty);
1994 utmp_wall("The system shutdown has been cancelled",
1995 lookup_uid(uid), tty, logind_wall_tty_filter, m);
1998 return sd_bus_reply_method_return(message, "b", cancelled);
2001 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2002 Manager *m = userdata;
2004 return method_do_shutdown_or_sleep(
2006 SPECIAL_HIBERNATE_TARGET,
2008 "org.freedesktop.login1.hibernate",
2009 "org.freedesktop.login1.hibernate-multiple-sessions",
2010 "org.freedesktop.login1.hibernate-ignore-inhibit",
2015 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2016 Manager *m = userdata;
2018 return method_do_shutdown_or_sleep(
2020 SPECIAL_HYBRID_SLEEP_TARGET,
2022 "org.freedesktop.login1.hibernate",
2023 "org.freedesktop.login1.hibernate-multiple-sessions",
2024 "org.freedesktop.login1.hibernate-ignore-inhibit",
2029 static int method_can_shutdown_or_sleep(
2031 sd_bus_message *message,
2034 const char *action_multiple_sessions,
2035 const char *action_ignore_inhibit,
2036 const char *sleep_verb,
2037 sd_bus_error *error) {
2039 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2040 bool multiple_sessions, challenge, blocked;
2041 const char *result = NULL;
2048 assert(w <= _INHIBIT_WHAT_MAX);
2050 assert(action_multiple_sessions);
2051 assert(action_ignore_inhibit);
2054 r = can_sleep(sleep_verb);
2058 return sd_bus_reply_method_return(message, "s", "na");
2061 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2065 r = sd_bus_creds_get_euid(creds, &uid);
2069 r = have_multiple_sessions(m, uid);
2073 multiple_sessions = r > 0;
2074 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2076 if (multiple_sessions) {
2077 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
2084 result = "challenge";
2090 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
2094 if (r > 0 && !result)
2096 else if (challenge && (!result || streq(result, "yes")))
2097 result = "challenge";
2102 if (!multiple_sessions && !blocked) {
2103 /* If neither inhibit nor multiple sessions
2104 * apply then just check the normal policy */
2106 r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
2113 result = "challenge";
2118 return sd_bus_reply_method_return(message, "s", result);
2121 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2122 Manager *m = userdata;
2124 return method_can_shutdown_or_sleep(
2127 "org.freedesktop.login1.power-off",
2128 "org.freedesktop.login1.power-off-multiple-sessions",
2129 "org.freedesktop.login1.power-off-ignore-inhibit",
2134 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2135 Manager *m = userdata;
2137 return method_can_shutdown_or_sleep(
2140 "org.freedesktop.login1.reboot",
2141 "org.freedesktop.login1.reboot-multiple-sessions",
2142 "org.freedesktop.login1.reboot-ignore-inhibit",
2147 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2148 Manager *m = userdata;
2150 return method_can_shutdown_or_sleep(
2153 "org.freedesktop.login1.suspend",
2154 "org.freedesktop.login1.suspend-multiple-sessions",
2155 "org.freedesktop.login1.suspend-ignore-inhibit",
2160 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2161 Manager *m = userdata;
2163 return method_can_shutdown_or_sleep(
2166 "org.freedesktop.login1.hibernate",
2167 "org.freedesktop.login1.hibernate-multiple-sessions",
2168 "org.freedesktop.login1.hibernate-ignore-inhibit",
2173 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2174 Manager *m = userdata;
2176 return method_can_shutdown_or_sleep(
2179 "org.freedesktop.login1.hibernate",
2180 "org.freedesktop.login1.hibernate-multiple-sessions",
2181 "org.freedesktop.login1.hibernate-ignore-inhibit",
2186 static int property_get_reboot_to_firmware_setup(
2189 const char *interface,
2190 const char *property,
2191 sd_bus_message *reply,
2193 sd_bus_error *error) {
2200 r = efi_get_reboot_to_firmware();
2201 if (r < 0 && r != -EOPNOTSUPP)
2204 return sd_bus_message_append(reply, "b", r > 0);
2207 static int method_set_reboot_to_firmware_setup(
2208 sd_bus_message *message,
2210 sd_bus_error *error) {
2213 Manager *m = userdata;
2218 r = sd_bus_message_read(message, "b", &b);
2222 r = bus_verify_polkit_async(message,
2224 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2227 &m->polkit_registry,
2232 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2234 r = efi_set_reboot_to_firmware(b);
2238 return sd_bus_reply_method_return(message, NULL);
2241 static int method_can_reboot_to_firmware_setup(
2242 sd_bus_message *message,
2244 sd_bus_error *error) {
2249 Manager *m = userdata;
2254 r = efi_reboot_to_firmware_supported();
2255 if (r == -EOPNOTSUPP)
2256 return sd_bus_reply_method_return(message, "s", "na");
2260 r = bus_test_polkit(message,
2262 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2272 result = "challenge";
2276 return sd_bus_reply_method_return(message, "s", result);
2279 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2280 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2281 const char *who, *why, *what, *mode;
2282 _cleanup_free_ char *id = NULL;
2283 _cleanup_close_ int fifo_fd = -1;
2284 Manager *m = userdata;
2285 Inhibitor *i = NULL;
2295 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2299 w = inhibit_what_from_string(what);
2301 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2303 mm = inhibit_mode_from_string(mode);
2305 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2307 /* Delay is only supported for shutdown/sleep */
2308 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2309 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2311 /* Don't allow taking delay locks while we are already
2312 * executing the operation. We shouldn't create the impression
2313 * that the lock was successful if the machine is about to go
2314 * down/suspend any moment. */
2315 if (m->action_what & w)
2316 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2318 r = bus_verify_polkit_async(
2321 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2322 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2323 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2324 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2325 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2326 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2327 "org.freedesktop.login1.inhibit-handle-lid-switch",
2330 &m->polkit_registry,
2335 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2337 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2341 r = sd_bus_creds_get_euid(creds, &uid);
2345 r = sd_bus_creds_get_pid(creds, &pid);
2353 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2356 } while (hashmap_get(m->inhibitors, id));
2358 r = manager_add_inhibitor(m, id, &i);
2366 i->why = strdup(why);
2367 i->who = strdup(who);
2369 if (!i->why || !i->who) {
2374 fifo_fd = inhibitor_create_fifo(i);
2382 return sd_bus_reply_method_return(message, "h", fifo_fd);
2391 const sd_bus_vtable manager_vtable[] = {
2392 SD_BUS_VTABLE_START(0),
2394 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2395 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2397 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2398 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2399 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2400 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2401 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2402 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2403 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2404 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2405 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2406 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2407 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2408 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2409 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2410 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2411 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2412 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2413 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2414 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2415 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2416 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2417 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2418 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2419 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2421 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2422 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2423 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2424 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2425 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2426 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2427 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2428 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2429 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2430 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2431 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2432 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2433 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2434 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2435 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2436 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2437 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2438 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2439 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2440 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2441 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2442 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2443 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2444 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2445 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2446 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2447 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2448 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2449 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2450 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2451 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2452 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2453 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2454 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2455 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2456 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2457 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2458 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2459 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2460 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2462 SD_BUS_SIGNAL("SessionNew", "so", 0),
2463 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2464 SD_BUS_SIGNAL("UserNew", "uo", 0),
2465 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2466 SD_BUS_SIGNAL("SeatNew", "so", 0),
2467 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2468 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2469 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2474 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2483 if (streq(result, "done"))
2484 r = session_send_create_reply(s, NULL);
2486 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2488 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2489 r = session_send_create_reply(s, &e);
2495 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2496 const char *path, *result, *unit;
2497 Manager *m = userdata;
2506 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2508 bus_log_parse_error(r);
2512 if (m->action_job && streq(m->action_job, path)) {
2513 log_info("Operation finished.");
2515 /* Tell people that they now may take a lock again */
2516 send_prepare_for(m, m->action_what, false);
2518 free(m->action_job);
2519 m->action_job = NULL;
2520 m->action_unit = NULL;
2525 session = hashmap_get(m->session_units, unit);
2528 if (streq_ptr(path, session->scope_job)) {
2529 free(session->scope_job);
2530 session->scope_job = NULL;
2533 session_jobs_reply(session, unit, result);
2535 session_save(session);
2536 user_save(session->user);
2537 session_add_to_gc_queue(session);
2540 user = hashmap_get(m->user_units, unit);
2543 if (streq_ptr(path, user->service_job)) {
2544 free(user->service_job);
2545 user->service_job = NULL;
2548 if (streq_ptr(path, user->slice_job)) {
2549 free(user->slice_job);
2550 user->slice_job = NULL;
2553 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2554 session_jobs_reply(session, unit, result);
2558 user_add_to_gc_queue(user);
2564 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2565 const char *path, *unit;
2566 Manager *m = userdata;
2574 r = sd_bus_message_read(message, "so", &unit, &path);
2576 bus_log_parse_error(r);
2580 session = hashmap_get(m->session_units, unit);
2582 session_add_to_gc_queue(session);
2584 user = hashmap_get(m->user_units, unit);
2586 user_add_to_gc_queue(user);
2591 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2592 _cleanup_free_ char *unit = NULL;
2593 Manager *m = userdata;
2602 path = sd_bus_message_get_path(message);
2606 r = unit_name_from_dbus_path(path, &unit);
2607 if (r == -EINVAL) /* not a unit */
2612 session = hashmap_get(m->session_units, unit);
2614 session_add_to_gc_queue(session);
2616 user = hashmap_get(m->user_units, unit);
2618 user_add_to_gc_queue(user);
2623 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2624 Manager *m = userdata;
2632 r = sd_bus_message_read(message, "b", &b);
2634 bus_log_parse_error(r);
2641 /* systemd finished reloading, let's recheck all our sessions */
2642 log_debug("System manager has been reloaded, rechecking sessions...");
2644 HASHMAP_FOREACH(session, m->sessions, i)
2645 session_add_to_gc_queue(session);
2650 int match_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2651 const char *name, *old, *new;
2652 Manager *m = userdata;
2661 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2663 bus_log_parse_error(r);
2667 if (isempty(old) || !isempty(new))
2670 key = set_remove(m->busnames, (char*) old);
2674 /* Drop all controllers owned by this name */
2678 HASHMAP_FOREACH(session, m->sessions, i)
2679 if (session_is_controller(session, old))
2680 session_drop_controller(session);
2685 int manager_send_changed(Manager *manager, const char *property, ...) {
2690 l = strv_from_stdarg_alloca(property);
2692 return sd_bus_emit_properties_changed_strv(
2694 "/org/freedesktop/login1",
2695 "org.freedesktop.login1.Manager",
2699 int manager_start_scope(
2704 const char *description,
2705 const char *after, const char *after2,
2706 sd_bus_error *error,
2709 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2716 r = sd_bus_message_new_method_call(
2719 "org.freedesktop.systemd1",
2720 "/org/freedesktop/systemd1",
2721 "org.freedesktop.systemd1.Manager",
2722 "StartTransientUnit");
2726 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2730 r = sd_bus_message_open_container(m, 'a', "(sv)");
2734 if (!isempty(slice)) {
2735 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2740 if (!isempty(description)) {
2741 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2746 if (!isempty(after)) {
2747 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2752 if (!isempty(after2)) {
2753 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2758 /* cgroup empty notification is not available in containers
2759 * currently. To make this less problematic, let's shorten the
2760 * stop timeout for sessions, so that we don't wait
2763 /* Make sure that the session shells are terminated with
2764 * SIGHUP since bash and friends tend to ignore SIGTERM */
2765 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2769 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2773 r = sd_bus_message_close_container(m);
2777 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2781 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2789 r = sd_bus_message_read(reply, "o", &j);
2803 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2804 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2810 r = sd_bus_call_method(
2812 "org.freedesktop.systemd1",
2813 "/org/freedesktop/systemd1",
2814 "org.freedesktop.systemd1.Manager",
2818 "ss", unit, "fail");
2826 r = sd_bus_message_read(reply, "o", &j);
2840 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2841 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2847 r = sd_bus_call_method(
2849 "org.freedesktop.systemd1",
2850 "/org/freedesktop/systemd1",
2851 "org.freedesktop.systemd1.Manager",
2855 "ss", unit, "fail");
2857 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2858 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2863 sd_bus_error_free(error);
2874 r = sd_bus_message_read(reply, "o", &j);
2888 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2889 _cleanup_free_ char *path = NULL;
2895 path = unit_dbus_path_from_name(scope);
2899 r = sd_bus_call_method(
2901 "org.freedesktop.systemd1",
2903 "org.freedesktop.systemd1.Scope",
2909 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2910 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2911 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2912 sd_bus_error_free(error);
2922 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2926 return sd_bus_call_method(
2928 "org.freedesktop.systemd1",
2929 "/org/freedesktop/systemd1",
2930 "org.freedesktop.systemd1.Manager",
2934 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2937 int manager_unit_is_active(Manager *manager, const char *unit) {
2938 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2939 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2940 _cleanup_free_ char *path = NULL;
2947 path = unit_dbus_path_from_name(unit);
2951 r = sd_bus_get_property(
2953 "org.freedesktop.systemd1",
2955 "org.freedesktop.systemd1.Unit",
2961 /* systemd might have droppped off momentarily, let's
2962 * not make this an error */
2963 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2964 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2967 /* If the unit is already unloaded then it's not
2969 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2970 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2976 r = sd_bus_message_read(reply, "s", &state);
2980 return !streq(state, "inactive") && !streq(state, "failed");
2983 int manager_job_is_active(Manager *manager, const char *path) {
2984 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2985 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2991 r = sd_bus_get_property(
2993 "org.freedesktop.systemd1",
2995 "org.freedesktop.systemd1.Job",
3001 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3002 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3005 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3011 /* We don't actually care about the state really. The fact
3012 * that we could read the job state is enough for us */