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;
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 method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
247 _cleanup_free_ char *p = NULL;
248 Manager *m = userdata;
257 r = sd_bus_message_read(message, "s", &name);
261 r = manager_get_session_from_creds(m, message, name, error, &session);
265 p = session_bus_path(session);
269 return sd_bus_reply_method_return(message, "o", p);
272 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
273 _cleanup_free_ char *p = NULL;
274 Session *session = NULL;
275 Manager *m = userdata;
283 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
285 r = sd_bus_message_read(message, "u", &pid);
290 r = manager_get_session_from_creds(m, message, NULL, error, &session);
294 r = manager_get_session_by_pid(m, pid, &session);
299 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
302 p = session_bus_path(session);
306 return sd_bus_reply_method_return(message, "o", p);
309 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
310 _cleanup_free_ char *p = NULL;
311 Manager *m = userdata;
320 r = sd_bus_message_read(message, "u", &uid);
324 r = manager_get_user_from_creds(m, message, uid, error, &user);
328 p = user_bus_path(user);
332 return sd_bus_reply_method_return(message, "o", p);
335 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
336 _cleanup_free_ char *p = NULL;
337 Manager *m = userdata;
346 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
348 r = sd_bus_message_read(message, "u", &pid);
353 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
357 r = manager_get_user_by_pid(m, pid, &user);
361 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);
364 p = user_bus_path(user);
368 return sd_bus_reply_method_return(message, "o", p);
371 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
372 _cleanup_free_ char *p = NULL;
373 Manager *m = userdata;
382 r = sd_bus_message_read(message, "s", &name);
386 r = manager_get_seat_from_creds(m, message, name, error, &seat);
390 p = seat_bus_path(seat);
394 return sd_bus_reply_method_return(message, "o", p);
397 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
398 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
399 Manager *m = userdata;
408 r = sd_bus_message_new_method_return(message, &reply);
412 r = sd_bus_message_open_container(reply, 'a', "(susso)");
416 HASHMAP_FOREACH(session, m->sessions, i) {
417 _cleanup_free_ char *p = NULL;
419 p = session_bus_path(session);
423 r = sd_bus_message_append(reply, "(susso)",
425 (uint32_t) session->user->uid,
427 session->seat ? session->seat->id : "",
433 r = sd_bus_message_close_container(reply);
437 return sd_bus_send(bus, reply, NULL);
440 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
441 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
442 Manager *m = userdata;
451 r = sd_bus_message_new_method_return(message, &reply);
455 r = sd_bus_message_open_container(reply, 'a', "(uso)");
459 HASHMAP_FOREACH(user, m->users, i) {
460 _cleanup_free_ char *p = NULL;
462 p = user_bus_path(user);
466 r = sd_bus_message_append(reply, "(uso)",
467 (uint32_t) user->uid,
474 r = sd_bus_message_close_container(reply);
478 return sd_bus_send(bus, reply, NULL);
481 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
482 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
483 Manager *m = userdata;
492 r = sd_bus_message_new_method_return(message, &reply);
496 r = sd_bus_message_open_container(reply, 'a', "(so)");
500 HASHMAP_FOREACH(seat, m->seats, i) {
501 _cleanup_free_ char *p = NULL;
503 p = seat_bus_path(seat);
507 r = sd_bus_message_append(reply, "(so)", seat->id, p);
512 r = sd_bus_message_close_container(reply);
516 return sd_bus_send(bus, reply, NULL);
519 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
520 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
521 Manager *m = userdata;
522 Inhibitor *inhibitor;
526 r = sd_bus_message_new_method_return(message, &reply);
530 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
534 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
536 r = sd_bus_message_append(reply, "(ssssuu)",
537 strempty(inhibit_what_to_string(inhibitor->what)),
538 strempty(inhibitor->who),
539 strempty(inhibitor->why),
540 strempty(inhibit_mode_to_string(inhibitor->mode)),
541 (uint32_t) inhibitor->uid,
542 (uint32_t) inhibitor->pid);
547 r = sd_bus_message_close_container(reply);
551 return sd_bus_send(bus, reply, NULL);
554 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
555 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
556 uint32_t uid, leader, audit_id = 0;
557 _cleanup_free_ char *id = NULL;
558 Session *session = NULL;
559 Manager *m = userdata;
572 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
577 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
580 t = _SESSION_TYPE_INVALID;
582 t = session_type_from_string(type);
584 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
588 c = _SESSION_CLASS_INVALID;
590 c = session_class_from_string(class);
592 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
595 if (isempty(desktop))
598 if (!string_is_safe(desktop))
599 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
605 seat = hashmap_get(m->seats, cseat);
607 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
610 if (tty_is_vc(tty)) {
615 else if (seat != m->seat0)
616 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);
618 v = vtnr_from_tty(tty);
620 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
624 else if (vtnr != (uint32_t) v)
625 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
627 } else if (tty_is_console(tty)) {
631 else if (seat != m->seat0)
632 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
635 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
639 if (seat_has_vts(seat)) {
640 if (!vtnr || vtnr > 63)
641 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
644 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
648 r = sd_bus_message_enter_container(message, 'a', "(sv)");
652 if (t == _SESSION_TYPE_INVALID) {
653 if (!isempty(display))
655 else if (!isempty(tty))
658 t = SESSION_UNSPECIFIED;
661 if (c == _SESSION_CLASS_INVALID) {
662 if (t == SESSION_UNSPECIFIED)
663 c = SESSION_BACKGROUND;
669 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
671 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
675 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
680 manager_get_session_by_pid(m, leader, &session);
682 _cleanup_free_ char *path = NULL;
683 _cleanup_close_ int fifo_fd = -1;
685 /* Session already exists, client is probably
686 * something like "su" which changes uid but is still
687 * the same session */
689 fifo_fd = session_create_fifo(session);
693 path = session_bus_path(session);
697 log_debug("Sending reply about an existing session: "
698 "id=%s object_path=%s uid=%u runtime_path=%s "
699 "session_fd=%d seat=%s vtnr=%u",
702 (uint32_t) session->user->uid,
703 session->user->runtime_path,
705 session->seat ? session->seat->id : "",
706 (uint32_t) session->vtnr);
708 return sd_bus_reply_method_return(
712 session->user->runtime_path,
714 (uint32_t) session->user->uid,
715 session->seat ? session->seat->id : "",
716 (uint32_t) session->vtnr,
720 audit_session_from_pid(leader, &audit_id);
722 /* Keep our session IDs and the audit session IDs in sync */
724 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
727 /* Wut? There's already a session by this name and we
728 * didn't find it above? Weird, then let's not trust
729 * the audit data and let's better register a new
731 if (hashmap_get(m->sessions, id)) {
732 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
745 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
748 } while (hashmap_get(m->sessions, id));
751 r = manager_add_user_by_uid(m, uid, &user);
755 r = manager_add_session(m, id, &session);
759 session_set_user(session, user);
761 session->leader = leader;
762 session->audit_id = audit_id;
765 session->remote = remote;
766 session->vtnr = vtnr;
769 session->tty = strdup(tty);
776 if (!isempty(display)) {
777 session->display = strdup(display);
778 if (!session->display) {
784 if (!isempty(remote_user)) {
785 session->remote_user = strdup(remote_user);
786 if (!session->remote_user) {
792 if (!isempty(remote_host)) {
793 session->remote_host = strdup(remote_host);
794 if (!session->remote_host) {
800 if (!isempty(service)) {
801 session->service = strdup(service);
802 if (!session->service) {
808 if (!isempty(desktop)) {
809 session->desktop = strdup(desktop);
810 if (!session->desktop) {
817 r = seat_attach_session(seat, session);
822 r = session_start(session);
826 session->create_message = sd_bus_message_ref(message);
828 /* Now, let's wait until the slice unit and stuff got
829 * created. We send the reply back from
830 * session_send_create_reply(). */
836 session_add_to_gc_queue(session);
839 user_add_to_gc_queue(user);
844 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
845 Manager *m = userdata;
854 r = sd_bus_message_read(message, "s", &name);
858 r = manager_get_session_from_creds(m, message, name, error, &session);
862 r = session_release(session);
866 return sd_bus_reply_method_return(message, NULL);
869 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
870 Manager *m = userdata;
879 r = sd_bus_message_read(message, "s", &name);
883 r = manager_get_session_from_creds(m, message, name, error, &session);
887 return bus_session_method_activate(bus, message, session, error);
890 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
891 const char *session_name, *seat_name;
892 Manager *m = userdata;
901 /* Same as ActivateSession() but refuses to work if
902 * the seat doesn't match */
904 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
908 r = manager_get_session_from_creds(m, message, session_name, error, &session);
912 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
916 if (session->seat != seat)
917 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
919 r = session_activate(session);
923 return sd_bus_reply_method_return(message, NULL);
926 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
927 Manager *m = userdata;
936 r = sd_bus_message_read(message, "s", &name);
940 r = manager_get_session_from_creds(m, message, name, error, &session);
944 return bus_session_method_lock(bus, message, session, error);
947 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
948 Manager *m = userdata;
955 r = bus_verify_polkit_async(
958 "org.freedesktop.login1.lock-sessions",
966 return 1; /* Will call us back */
968 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
972 return sd_bus_reply_method_return(message, NULL);
975 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
977 Manager *m = userdata;
985 r = sd_bus_message_read(message, "s", &name);
989 r = manager_get_session_from_creds(m, message, name, error, &session);
993 return bus_session_method_kill(bus, message, session, error);
996 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
997 Manager *m = userdata;
1006 r = sd_bus_message_read(message, "u", &uid);
1010 r = manager_get_user_from_creds(m, message, uid, error, &user);
1014 return bus_user_method_kill(bus, message, user, error);
1017 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1018 Manager *m = userdata;
1027 r = sd_bus_message_read(message, "s", &name);
1031 r = manager_get_session_from_creds(m, message, name, error, &session);
1035 return bus_session_method_terminate(bus, message, session, error);
1038 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1039 Manager *m = userdata;
1048 r = sd_bus_message_read(message, "u", &uid);
1052 r = manager_get_user_from_creds(m, message, uid, error, &user);
1056 return bus_user_method_terminate(bus, message, user, error);
1059 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1060 Manager *m = userdata;
1069 r = sd_bus_message_read(message, "s", &name);
1073 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1077 return bus_seat_method_terminate(bus, message, seat, error);
1080 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1081 _cleanup_free_ char *cc = NULL;
1082 Manager *m = userdata;
1093 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1097 if (uid == UID_INVALID) {
1098 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1100 /* Note that we get the owner UID of the session, not the actual client UID here! */
1101 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1105 r = sd_bus_creds_get_owner_uid(creds, &uid);
1113 return errno ? -errno : -ENOENT;
1115 r = bus_verify_polkit_async(
1118 "org.freedesktop.login1.set-user-linger",
1121 &m->polkit_registry,
1126 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1128 mkdir_p_label("/var/lib/systemd", 0755);
1130 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1134 cc = cescape(pw->pw_name);
1138 path = strjoina("/var/lib/systemd/linger/", cc);
1146 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1153 if (r < 0 && errno != ENOENT)
1156 u = hashmap_get(m->users, UID_TO_PTR(uid));
1158 user_add_to_gc_queue(u);
1161 return sd_bus_reply_method_return(message, NULL);
1164 static int trigger_device(Manager *m, struct udev_device *d) {
1165 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1166 struct udev_list_entry *first, *item;
1171 e = udev_enumerate_new(m->udev);
1176 r = udev_enumerate_add_match_parent(e, d);
1181 r = udev_enumerate_scan_devices(e);
1185 first = udev_enumerate_get_list_entry(e);
1186 udev_list_entry_foreach(item, first) {
1187 _cleanup_free_ char *t = NULL;
1190 p = udev_list_entry_get_name(item);
1192 t = strappend(p, "/uevent");
1196 write_string_file(t, "change");
1202 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1203 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1204 _cleanup_free_ char *rule = NULL, *file = NULL;
1205 const char *id_for_seat;
1212 d = udev_device_new_from_syspath(m->udev, sysfs);
1216 if (!udev_device_has_tag(d, "seat"))
1219 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1223 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1226 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1229 mkdir_p_label("/etc/udev/rules.d", 0755);
1230 mac_selinux_init("/etc");
1231 r = write_string_file_atomic_label(file, rule);
1235 return trigger_device(m, d);
1238 static int flush_devices(Manager *m) {
1239 _cleanup_closedir_ DIR *d;
1243 d = opendir("/etc/udev/rules.d");
1245 if (errno != ENOENT)
1246 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1250 while ((de = readdir(d))) {
1252 if (!dirent_is_file(de))
1255 if (!startswith(de->d_name, "72-seat-"))
1258 if (!endswith(de->d_name, ".rules"))
1261 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1262 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1266 return trigger_device(m, NULL);
1269 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1270 const char *sysfs, *seat;
1271 Manager *m = userdata;
1278 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1282 if (!path_startswith(sysfs, "/sys"))
1283 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1285 if (!seat_name_is_valid(seat))
1286 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1288 r = bus_verify_polkit_async(
1291 "org.freedesktop.login1.attach-device",
1294 &m->polkit_registry,
1299 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1301 r = attach_device(m, seat, sysfs);
1305 return sd_bus_reply_method_return(message, NULL);
1308 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1309 Manager *m = userdata;
1316 r = sd_bus_message_read(message, "b", &interactive);
1320 r = bus_verify_polkit_async(
1323 "org.freedesktop.login1.flush-devices",
1326 &m->polkit_registry,
1331 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1333 r = flush_devices(m);
1337 return sd_bus_reply_method_return(message, NULL);
1340 static int have_multiple_sessions(
1349 /* Check for other users' sessions. Greeter sessions do not
1350 * count, and non-login sessions do not count either. */
1351 HASHMAP_FOREACH(session, m->sessions, i)
1352 if (session->class == SESSION_USER &&
1353 session->user->uid != uid)
1359 static int bus_manager_log_shutdown(
1362 const char *unit_name) {
1369 if (w != INHIBIT_SHUTDOWN)
1372 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1373 p = "MESSAGE=System is powering down.";
1374 q = "SHUTDOWN=power-off";
1375 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1376 p = "MESSAGE=System is halting.";
1377 q = "SHUTDOWN=halt";
1378 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1379 p = "MESSAGE=System is rebooting.";
1380 q = "SHUTDOWN=reboot";
1381 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1382 p = "MESSAGE=System is rebooting with kexec.";
1383 q = "SHUTDOWN=kexec";
1385 p = "MESSAGE=System is shutting down.";
1389 return log_struct(LOG_NOTICE,
1390 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1396 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1397 Manager *m = userdata;
1402 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1406 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1411 if (until <= now(CLOCK_MONOTONIC))
1414 /* We want to ignore the lid switch for a while after each
1415 * suspend, and after boot-up. Hence let's install a timer for
1416 * this. As long as the event source exists we ignore the lid
1419 if (m->lid_switch_ignore_event_source) {
1422 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1429 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1431 r = sd_event_add_time(
1433 &m->lid_switch_ignore_event_source,
1436 lid_switch_ignore_handler, m);
1441 static int execute_shutdown_or_sleep(
1444 const char *unit_name,
1445 sd_bus_error *error) {
1447 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1454 assert(w < _INHIBIT_WHAT_MAX);
1457 bus_manager_log_shutdown(m, w, unit_name);
1459 r = sd_bus_call_method(
1461 "org.freedesktop.systemd1",
1462 "/org/freedesktop/systemd1",
1463 "org.freedesktop.systemd1.Manager",
1467 "ss", unit_name, "replace-irreversibly");
1471 r = sd_bus_message_read(reply, "o", &p);
1479 m->action_unit = unit_name;
1480 free(m->action_job);
1484 /* Make sure the lid switch is ignored for a while */
1485 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1490 static int manager_inhibit_timeout_handler(
1495 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1496 Inhibitor *offending = NULL;
1497 Manager *manager = userdata;
1501 assert(manager->inhibit_timeout_source == s);
1503 if (manager->action_what == 0 || manager->action_job)
1506 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1507 _cleanup_free_ char *comm = NULL, *u = NULL;
1509 (void) get_process_comm(offending->pid, &comm);
1510 u = uid_to_name(offending->uid);
1512 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1513 offending->uid, strna(u),
1514 offending->pid, strna(comm));
1517 /* Actually do the operation */
1518 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1520 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1522 manager->action_unit = NULL;
1523 manager->action_what = 0;
1529 static int delay_shutdown_or_sleep(
1532 const char *unit_name) {
1539 assert(w < _INHIBIT_WHAT_MAX);
1542 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1544 if (m->inhibit_timeout_source) {
1545 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1547 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1549 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1551 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1553 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1554 timeout_val, 0, manager_inhibit_timeout_handler, m);
1559 m->action_unit = unit_name;
1565 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1567 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1568 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1569 [INHIBIT_SLEEP] = "PrepareForSleep"
1572 int active = _active;
1576 assert(w < _INHIBIT_WHAT_MAX);
1577 assert(signal_name[w]);
1579 return sd_bus_emit_signal(m->bus,
1580 "/org/freedesktop/login1",
1581 "org.freedesktop.login1.Manager",
1587 int bus_manager_shutdown_or_sleep_now_or_later(
1589 const char *unit_name,
1591 sd_bus_error *error) {
1599 assert(w <= _INHIBIT_WHAT_MAX);
1600 assert(!m->action_job);
1602 /* Tell everybody to prepare for shutdown/sleep */
1603 send_prepare_for(m, w, true);
1606 m->inhibit_delay_max > 0 &&
1607 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1610 /* Shutdown is delayed, keep in mind what we
1611 * want to do, and start a timeout */
1612 r = delay_shutdown_or_sleep(m, w, unit_name);
1614 /* Shutdown is not delayed, execute it
1616 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1621 static int verify_shutdown_creds(
1623 sd_bus_message *message,
1627 const char *action_multiple_sessions,
1628 const char *action_ignore_inhibit,
1629 sd_bus_error *error) {
1631 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1632 bool multiple_sessions, blocked;
1639 assert(w <= _INHIBIT_WHAT_MAX);
1641 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1645 r = sd_bus_creds_get_euid(creds, &uid);
1649 r = have_multiple_sessions(m, uid);
1653 multiple_sessions = r > 0;
1654 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1656 if (multiple_sessions && action_multiple_sessions) {
1657 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1661 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1664 if (blocked && action_ignore_inhibit) {
1665 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1669 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1672 if (!multiple_sessions && !blocked && action) {
1673 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1677 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1683 static int method_do_shutdown_or_sleep(
1685 sd_bus_message *message,
1686 const char *unit_name,
1689 const char *action_multiple_sessions,
1690 const char *action_ignore_inhibit,
1691 const char *sleep_verb,
1692 sd_bus_error *error) {
1700 assert(w <= _INHIBIT_WHAT_MAX);
1702 r = sd_bus_message_read(message, "b", &interactive);
1706 /* Don't allow multiple jobs being executed at the same time */
1708 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1711 r = can_sleep(sleep_verb);
1716 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1719 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1720 action_ignore_inhibit, error);
1724 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1728 return sd_bus_reply_method_return(message, NULL);
1731 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1732 Manager *m = userdata;
1734 return method_do_shutdown_or_sleep(
1736 SPECIAL_POWEROFF_TARGET,
1738 "org.freedesktop.login1.power-off",
1739 "org.freedesktop.login1.power-off-multiple-sessions",
1740 "org.freedesktop.login1.power-off-ignore-inhibit",
1745 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1746 Manager *m = userdata;
1748 return method_do_shutdown_or_sleep(
1750 SPECIAL_REBOOT_TARGET,
1752 "org.freedesktop.login1.reboot",
1753 "org.freedesktop.login1.reboot-multiple-sessions",
1754 "org.freedesktop.login1.reboot-ignore-inhibit",
1759 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1760 Manager *m = userdata;
1762 return method_do_shutdown_or_sleep(
1764 SPECIAL_SUSPEND_TARGET,
1766 "org.freedesktop.login1.suspend",
1767 "org.freedesktop.login1.suspend-multiple-sessions",
1768 "org.freedesktop.login1.suspend-ignore-inhibit",
1773 static int nologin_timeout_handler(
1778 Manager *m = userdata;
1781 log_info("Creating /run/nologin, blocking further logins...");
1783 r = write_string_file_atomic("/run/nologin", "System is going down.");
1785 log_error_errno(r, "Failed to create /run/nologin: %m");
1787 m->unlink_nologin = true;
1792 static int update_schedule_file(Manager *m) {
1795 _cleanup_fclose_ FILE *f = NULL;
1796 _cleanup_free_ char *t = NULL, *temp_path = NULL;
1800 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1802 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1804 t = cescape(m->wall_message);
1808 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1810 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1812 (void) fchmod(fileno(f), 0644);
1818 m->scheduled_shutdown_timeout,
1819 m->enable_wall_messages,
1820 m->scheduled_shutdown_type);
1822 if (!isempty(m->wall_message))
1823 fprintf(f, "WALL_MESSAGE=%s\n", t);
1825 (void) fflush_and_check(f);
1827 if (ferror(f) || rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1828 log_error_errno(errno, "Failed to write information about scheduled shutdowns: %m");
1831 (void) unlink(temp_path);
1832 (void) unlink("/run/systemd/shutdown/scheduled");
1838 static int manager_scheduled_shutdown_handler(
1843 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1844 Manager *m = userdata;
1850 if (isempty(m->scheduled_shutdown_type))
1853 if (streq(m->scheduled_shutdown_type, "halt"))
1854 target = SPECIAL_HALT_TARGET;
1855 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1856 target = SPECIAL_POWEROFF_TARGET;
1858 target = SPECIAL_REBOOT_TARGET;
1860 r = execute_shutdown_or_sleep(m, 0, target, &error);
1862 return log_error_errno(r, "Unable to execute transition to %s: %m", target);
1867 static int method_schedule_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1868 Manager *m = userdata;
1869 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1870 const char *action_multiple_sessions = NULL;
1871 const char *action_ignore_inhibit = NULL;
1872 const char *action = NULL;
1880 r = sd_bus_message_read(message, "st", &type, &elapse);
1884 if (streq(type, "reboot")) {
1885 action = "org.freedesktop.login1.reboot";
1886 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1887 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1888 } else if (streq(type, "halt")) {
1889 action = "org.freedesktop.login1.halt";
1890 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1891 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1892 } else if (streq(type, "poweroff")) {
1893 action = "org.freedesktop.login1.poweroff";
1894 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1895 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1897 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1899 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1900 action, action_multiple_sessions, action_ignore_inhibit, error);
1904 if (m->scheduled_shutdown_timeout_source) {
1905 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1907 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1909 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
1911 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1913 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
1914 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
1916 return log_error_errno(r, "sd_event_add_time() failed: %m");
1919 r = free_and_strdup(&m->scheduled_shutdown_type, type);
1921 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1925 if (m->nologin_timeout_source) {
1926 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
1928 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1930 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
1932 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1934 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
1935 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
1937 return log_error_errno(r, "sd_event_add_time() failed: %m");
1940 m->scheduled_shutdown_timeout = elapse;
1942 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1946 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
1947 (void) sd_bus_creds_get_tty(creds, &tty);
1949 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
1951 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1956 r = manager_setup_wall_message_timer(m);
1960 if (!isempty(type)) {
1961 r = update_schedule_file(m);
1965 (void) unlink("/run/systemd/shutdown/scheduled");
1967 return sd_bus_reply_method_return(message, NULL);
1970 static int method_cancel_scheduled_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1971 Manager *m = userdata;
1977 cancelled = m->scheduled_shutdown_type != NULL;
1979 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1980 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
1981 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
1982 free(m->scheduled_shutdown_type);
1983 m->scheduled_shutdown_type = NULL;
1984 m->scheduled_shutdown_timeout = 0;
1987 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1988 const char *tty = NULL;
1992 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1994 (void) sd_bus_creds_get_uid(creds, &uid);
1995 (void) sd_bus_creds_get_tty(creds, &tty);
1998 utmp_wall("The system shutdown has been cancelled",
1999 lookup_uid(uid), tty, logind_wall_tty_filter, m);
2002 return sd_bus_reply_method_return(message, "b", cancelled);
2005 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2006 Manager *m = userdata;
2008 return method_do_shutdown_or_sleep(
2010 SPECIAL_HIBERNATE_TARGET,
2012 "org.freedesktop.login1.hibernate",
2013 "org.freedesktop.login1.hibernate-multiple-sessions",
2014 "org.freedesktop.login1.hibernate-ignore-inhibit",
2019 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2020 Manager *m = userdata;
2022 return method_do_shutdown_or_sleep(
2024 SPECIAL_HYBRID_SLEEP_TARGET,
2026 "org.freedesktop.login1.hibernate",
2027 "org.freedesktop.login1.hibernate-multiple-sessions",
2028 "org.freedesktop.login1.hibernate-ignore-inhibit",
2033 static int method_can_shutdown_or_sleep(
2035 sd_bus_message *message,
2038 const char *action_multiple_sessions,
2039 const char *action_ignore_inhibit,
2040 const char *sleep_verb,
2041 sd_bus_error *error) {
2043 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2044 bool multiple_sessions, challenge, blocked;
2045 const char *result = NULL;
2052 assert(w <= _INHIBIT_WHAT_MAX);
2054 assert(action_multiple_sessions);
2055 assert(action_ignore_inhibit);
2058 r = can_sleep(sleep_verb);
2062 return sd_bus_reply_method_return(message, "s", "na");
2065 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2069 r = sd_bus_creds_get_euid(creds, &uid);
2073 r = have_multiple_sessions(m, uid);
2077 multiple_sessions = r > 0;
2078 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2080 if (multiple_sessions) {
2081 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
2088 result = "challenge";
2094 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
2098 if (r > 0 && !result)
2100 else if (challenge && (!result || streq(result, "yes")))
2101 result = "challenge";
2106 if (!multiple_sessions && !blocked) {
2107 /* If neither inhibit nor multiple sessions
2108 * apply then just check the normal policy */
2110 r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
2117 result = "challenge";
2122 return sd_bus_reply_method_return(message, "s", result);
2125 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2126 Manager *m = userdata;
2128 return method_can_shutdown_or_sleep(
2131 "org.freedesktop.login1.power-off",
2132 "org.freedesktop.login1.power-off-multiple-sessions",
2133 "org.freedesktop.login1.power-off-ignore-inhibit",
2138 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2139 Manager *m = userdata;
2141 return method_can_shutdown_or_sleep(
2144 "org.freedesktop.login1.reboot",
2145 "org.freedesktop.login1.reboot-multiple-sessions",
2146 "org.freedesktop.login1.reboot-ignore-inhibit",
2151 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2152 Manager *m = userdata;
2154 return method_can_shutdown_or_sleep(
2157 "org.freedesktop.login1.suspend",
2158 "org.freedesktop.login1.suspend-multiple-sessions",
2159 "org.freedesktop.login1.suspend-ignore-inhibit",
2164 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2165 Manager *m = userdata;
2167 return method_can_shutdown_or_sleep(
2170 "org.freedesktop.login1.hibernate",
2171 "org.freedesktop.login1.hibernate-multiple-sessions",
2172 "org.freedesktop.login1.hibernate-ignore-inhibit",
2177 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2178 Manager *m = userdata;
2180 return method_can_shutdown_or_sleep(
2183 "org.freedesktop.login1.hibernate",
2184 "org.freedesktop.login1.hibernate-multiple-sessions",
2185 "org.freedesktop.login1.hibernate-ignore-inhibit",
2190 static int property_get_reboot_to_firmware_setup(
2193 const char *interface,
2194 const char *property,
2195 sd_bus_message *reply,
2197 sd_bus_error *error) {
2204 r = efi_get_reboot_to_firmware();
2205 if (r < 0 && r != -EOPNOTSUPP)
2208 return sd_bus_message_append(reply, "b", r > 0);
2211 static int method_set_reboot_to_firmware_setup(
2213 sd_bus_message *message,
2215 sd_bus_error *error) {
2218 Manager *m = userdata;
2224 r = sd_bus_message_read(message, "b", &b);
2228 r = bus_verify_polkit_async(message,
2230 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2233 &m->polkit_registry,
2238 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2240 r = efi_set_reboot_to_firmware(b);
2244 return sd_bus_reply_method_return(message, NULL);
2247 static int method_can_reboot_to_firmware_setup(
2249 sd_bus_message *message,
2251 sd_bus_error *error) {
2256 Manager *m = userdata;
2262 r = efi_reboot_to_firmware_supported();
2263 if (r == -EOPNOTSUPP)
2264 return sd_bus_reply_method_return(message, "s", "na");
2268 r = bus_test_polkit(message,
2270 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2280 result = "challenge";
2284 return sd_bus_reply_method_return(message, "s", result);
2287 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2288 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2289 const char *who, *why, *what, *mode;
2290 _cleanup_free_ char *id = NULL;
2291 _cleanup_close_ int fifo_fd = -1;
2292 Manager *m = userdata;
2293 Inhibitor *i = NULL;
2304 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2308 w = inhibit_what_from_string(what);
2310 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2312 mm = inhibit_mode_from_string(mode);
2314 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2316 /* Delay is only supported for shutdown/sleep */
2317 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2318 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2320 /* Don't allow taking delay locks while we are already
2321 * executing the operation. We shouldn't create the impression
2322 * that the lock was successful if the machine is about to go
2323 * down/suspend any moment. */
2324 if (m->action_what & w)
2325 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2327 r = bus_verify_polkit_async(
2330 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2331 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2332 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2333 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2334 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2335 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2336 "org.freedesktop.login1.inhibit-handle-lid-switch",
2339 &m->polkit_registry,
2344 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2346 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2350 r = sd_bus_creds_get_euid(creds, &uid);
2354 r = sd_bus_creds_get_pid(creds, &pid);
2362 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2365 } while (hashmap_get(m->inhibitors, id));
2367 r = manager_add_inhibitor(m, id, &i);
2375 i->why = strdup(why);
2376 i->who = strdup(who);
2378 if (!i->why || !i->who) {
2383 fifo_fd = inhibitor_create_fifo(i);
2391 return sd_bus_reply_method_return(message, "h", fifo_fd);
2400 const sd_bus_vtable manager_vtable[] = {
2401 SD_BUS_VTABLE_START(0),
2403 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2404 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2406 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2407 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2408 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2409 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2410 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2411 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2412 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2413 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2414 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2415 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2416 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2417 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2418 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2419 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2420 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2421 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2422 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2423 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2424 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2425 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2426 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2427 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2429 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2430 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2431 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2432 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2433 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2434 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2435 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2436 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2437 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2438 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2439 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2440 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2441 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2442 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2443 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2444 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2445 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2446 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2447 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2448 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2449 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2450 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2451 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2452 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2453 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2454 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2455 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2456 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2457 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2458 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2459 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2460 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2461 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2462 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2463 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2464 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2465 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2466 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2467 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2468 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2470 SD_BUS_SIGNAL("SessionNew", "so", 0),
2471 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2472 SD_BUS_SIGNAL("UserNew", "uo", 0),
2473 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2474 SD_BUS_SIGNAL("SeatNew", "so", 0),
2475 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2476 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2477 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2482 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2491 if (streq(result, "done"))
2492 r = session_send_create_reply(s, NULL);
2494 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2496 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2497 r = session_send_create_reply(s, &e);
2503 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2504 const char *path, *result, *unit;
2505 Manager *m = userdata;
2515 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2517 bus_log_parse_error(r);
2521 if (m->action_job && streq(m->action_job, path)) {
2522 log_info("Operation finished.");
2524 /* Tell people that they now may take a lock again */
2525 send_prepare_for(m, m->action_what, false);
2527 free(m->action_job);
2528 m->action_job = NULL;
2529 m->action_unit = NULL;
2534 session = hashmap_get(m->session_units, unit);
2537 if (streq_ptr(path, session->scope_job)) {
2538 free(session->scope_job);
2539 session->scope_job = NULL;
2542 session_jobs_reply(session, unit, result);
2544 session_save(session);
2545 session_add_to_gc_queue(session);
2548 user = hashmap_get(m->user_units, unit);
2551 if (streq_ptr(path, user->service_job)) {
2552 free(user->service_job);
2553 user->service_job = NULL;
2556 if (streq_ptr(path, user->slice_job)) {
2557 free(user->slice_job);
2558 user->slice_job = NULL;
2561 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2562 session_jobs_reply(session, unit, result);
2566 user_add_to_gc_queue(user);
2572 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2573 const char *path, *unit;
2574 Manager *m = userdata;
2583 r = sd_bus_message_read(message, "so", &unit, &path);
2585 bus_log_parse_error(r);
2589 session = hashmap_get(m->session_units, unit);
2591 session_add_to_gc_queue(session);
2593 user = hashmap_get(m->user_units, unit);
2595 user_add_to_gc_queue(user);
2600 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2601 _cleanup_free_ char *unit = NULL;
2602 Manager *m = userdata;
2612 path = sd_bus_message_get_path(message);
2616 r = unit_name_from_dbus_path(path, &unit);
2617 if (r == -EINVAL) /* not a unit */
2622 session = hashmap_get(m->session_units, unit);
2624 session_add_to_gc_queue(session);
2626 user = hashmap_get(m->user_units, unit);
2628 user_add_to_gc_queue(user);
2633 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2634 Manager *m = userdata;
2641 r = sd_bus_message_read(message, "b", &b);
2643 bus_log_parse_error(r);
2650 /* systemd finished reloading, let's recheck all our sessions */
2651 log_debug("System manager has been reloaded, rechecking sessions...");
2653 HASHMAP_FOREACH(session, m->sessions, i)
2654 session_add_to_gc_queue(session);
2659 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2660 const char *name, *old, *new;
2661 Manager *m = userdata;
2669 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2671 bus_log_parse_error(r);
2675 if (isempty(old) || !isempty(new))
2678 key = set_remove(m->busnames, (char*) old);
2682 /* Drop all controllers owned by this name */
2686 HASHMAP_FOREACH(session, m->sessions, i)
2687 if (session_is_controller(session, old))
2688 session_drop_controller(session);
2693 int manager_send_changed(Manager *manager, const char *property, ...) {
2698 l = strv_from_stdarg_alloca(property);
2700 return sd_bus_emit_properties_changed_strv(
2702 "/org/freedesktop/login1",
2703 "org.freedesktop.login1.Manager",
2707 int manager_start_scope(
2712 const char *description,
2713 const char *after, const char *after2,
2714 sd_bus_error *error,
2717 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2724 r = sd_bus_message_new_method_call(
2727 "org.freedesktop.systemd1",
2728 "/org/freedesktop/systemd1",
2729 "org.freedesktop.systemd1.Manager",
2730 "StartTransientUnit");
2734 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2738 r = sd_bus_message_open_container(m, 'a', "(sv)");
2742 if (!isempty(slice)) {
2743 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2748 if (!isempty(description)) {
2749 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2754 if (!isempty(after)) {
2755 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2760 if (!isempty(after2)) {
2761 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2766 /* cgroup empty notification is not available in containers
2767 * currently. To make this less problematic, let's shorten the
2768 * stop timeout for sessions, so that we don't wait
2771 /* Make sure that the session shells are terminated with
2772 * SIGHUP since bash and friends tend to ignore SIGTERM */
2773 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2777 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2781 r = sd_bus_message_close_container(m);
2785 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2789 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2797 r = sd_bus_message_read(reply, "o", &j);
2811 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2812 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2818 r = sd_bus_call_method(
2820 "org.freedesktop.systemd1",
2821 "/org/freedesktop/systemd1",
2822 "org.freedesktop.systemd1.Manager",
2826 "ss", unit, "fail");
2834 r = sd_bus_message_read(reply, "o", &j);
2848 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2849 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2855 r = sd_bus_call_method(
2857 "org.freedesktop.systemd1",
2858 "/org/freedesktop/systemd1",
2859 "org.freedesktop.systemd1.Manager",
2863 "ss", unit, "fail");
2865 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2866 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2871 sd_bus_error_free(error);
2882 r = sd_bus_message_read(reply, "o", &j);
2896 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2897 _cleanup_free_ char *path = NULL;
2903 path = unit_dbus_path_from_name(scope);
2907 r = sd_bus_call_method(
2909 "org.freedesktop.systemd1",
2911 "org.freedesktop.systemd1.Scope",
2917 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2918 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2919 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2920 sd_bus_error_free(error);
2930 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2934 return sd_bus_call_method(
2936 "org.freedesktop.systemd1",
2937 "/org/freedesktop/systemd1",
2938 "org.freedesktop.systemd1.Manager",
2942 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2945 int manager_unit_is_active(Manager *manager, const char *unit) {
2946 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2947 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2948 _cleanup_free_ char *path = NULL;
2955 path = unit_dbus_path_from_name(unit);
2959 r = sd_bus_get_property(
2961 "org.freedesktop.systemd1",
2963 "org.freedesktop.systemd1.Unit",
2969 /* systemd might have droppped off momentarily, let's
2970 * not make this an error */
2971 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2972 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2975 /* If the unit is already unloaded then it's not
2977 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2978 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2984 r = sd_bus_message_read(reply, "s", &state);
2988 return !streq(state, "inactive") && !streq(state, "failed");
2991 int manager_job_is_active(Manager *manager, const char *path) {
2992 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2993 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2999 r = sd_bus_get_property(
3001 "org.freedesktop.systemd1",
3003 "org.freedesktop.systemd1.Job",
3009 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3010 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3013 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3019 /* We don't actually care about the state really. The fact
3020 * that we could read the job state is enough for us */