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"
31 // #include "special.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. Furthermore, to allow
703 * re-logins, we have to allow a greeter to take over a used VT for
704 * the exact same reasons.
706 if (c != SESSION_GREETER &&
708 vtnr < m->seat0->position_count &&
709 m->seat0->positions[vtnr] &&
710 m->seat0->positions[vtnr]->class != SESSION_GREETER)
711 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
713 audit_session_from_pid(leader, &audit_id);
715 /* Keep our session IDs and the audit session IDs in sync */
717 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
720 /* Wut? There's already a session by this name and we
721 * didn't find it above? Weird, then let's not trust
722 * the audit data and let's better register a new
724 if (hashmap_get(m->sessions, id)) {
725 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
736 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
739 } while (hashmap_get(m->sessions, id));
742 r = manager_add_user_by_uid(m, uid, &user);
746 r = manager_add_session(m, id, &session);
750 session_set_user(session, user);
752 session->leader = leader;
753 session->audit_id = audit_id;
756 session->remote = remote;
757 session->vtnr = vtnr;
760 session->tty = strdup(tty);
767 if (!isempty(display)) {
768 session->display = strdup(display);
769 if (!session->display) {
775 if (!isempty(remote_user)) {
776 session->remote_user = strdup(remote_user);
777 if (!session->remote_user) {
783 if (!isempty(remote_host)) {
784 session->remote_host = strdup(remote_host);
785 if (!session->remote_host) {
791 if (!isempty(service)) {
792 session->service = strdup(service);
793 if (!session->service) {
799 if (!isempty(desktop)) {
800 session->desktop = strdup(desktop);
801 if (!session->desktop) {
808 r = seat_attach_session(seat, session);
813 r = session_start(session);
817 session->create_message = sd_bus_message_ref(message);
819 /* Here upstream systemd starts cgroups and the user systemd,
820 and arranges to reply asynchronously. We reply
823 r = session_send_create_reply(session, NULL);
831 session_add_to_gc_queue(session);
834 user_add_to_gc_queue(user);
839 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
840 Manager *m = userdata;
848 r = sd_bus_message_read(message, "s", &name);
852 r = manager_get_session_from_creds(m, message, name, error, &session);
856 r = session_release(session);
860 session_add_to_gc_queue(session);
862 return sd_bus_reply_method_return(message, NULL);
865 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
866 Manager *m = userdata;
874 r = sd_bus_message_read(message, "s", &name);
878 r = manager_get_session_from_creds(m, message, name, error, &session);
882 return bus_session_method_activate(message, session, error);
885 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
886 const char *session_name, *seat_name;
887 Manager *m = userdata;
895 /* Same as ActivateSession() but refuses to work if
896 * the seat doesn't match */
898 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
902 r = manager_get_session_from_creds(m, message, session_name, error, &session);
906 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
910 if (session->seat != seat)
911 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
913 r = session_activate(session);
917 return sd_bus_reply_method_return(message, NULL);
920 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
921 Manager *m = userdata;
929 r = sd_bus_message_read(message, "s", &name);
933 r = manager_get_session_from_creds(m, message, name, error, &session);
937 return bus_session_method_lock(message, session, error);
940 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
941 Manager *m = userdata;
947 r = bus_verify_polkit_async(
950 "org.freedesktop.login1.lock-sessions",
959 return 1; /* Will call us back */
961 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
965 return sd_bus_reply_method_return(message, NULL);
968 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
970 Manager *m = userdata;
977 r = sd_bus_message_read(message, "s", &name);
981 r = manager_get_session_from_creds(m, message, name, error, &session);
985 return bus_session_method_kill(message, session, error);
988 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
989 Manager *m = userdata;
997 r = sd_bus_message_read(message, "u", &uid);
1001 r = manager_get_user_from_creds(m, message, uid, error, &user);
1005 return bus_user_method_kill(message, user, error);
1008 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1009 Manager *m = userdata;
1017 r = sd_bus_message_read(message, "s", &name);
1021 r = manager_get_session_from_creds(m, message, name, error, &session);
1025 return bus_session_method_terminate(message, session, error);
1028 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1029 Manager *m = userdata;
1037 r = sd_bus_message_read(message, "u", &uid);
1041 r = manager_get_user_from_creds(m, message, uid, error, &user);
1045 return bus_user_method_terminate(message, user, error);
1048 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1049 Manager *m = userdata;
1057 r = sd_bus_message_read(message, "s", &name);
1061 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1065 return bus_seat_method_terminate(message, seat, error);
1068 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1069 _cleanup_free_ char *cc = NULL;
1070 Manager *m = userdata;
1080 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1084 if (uid == UID_INVALID) {
1085 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1087 /* Note that we get the owner UID of the session, not the actual client UID here! */
1088 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1092 r = sd_bus_creds_get_owner_uid(creds, &uid);
1100 return errno ? -errno : -ENOENT;
1102 r = bus_verify_polkit_async(
1105 "org.freedesktop.login1.set-user-linger",
1109 &m->polkit_registry,
1114 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1116 mkdir_p_label("/var/lib/systemd", 0755);
1118 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1122 cc = cescape(pw->pw_name);
1126 path = strjoina("/var/lib/systemd/linger/", cc);
1134 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1141 if (r < 0 && errno != ENOENT)
1144 u = hashmap_get(m->users, UID_TO_PTR(uid));
1146 user_add_to_gc_queue(u);
1149 return sd_bus_reply_method_return(message, NULL);
1152 static int trigger_device(Manager *m, struct udev_device *d) {
1153 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1154 struct udev_list_entry *first, *item;
1159 e = udev_enumerate_new(m->udev);
1164 r = udev_enumerate_add_match_parent(e, d);
1169 r = udev_enumerate_scan_devices(e);
1173 first = udev_enumerate_get_list_entry(e);
1174 udev_list_entry_foreach(item, first) {
1175 _cleanup_free_ char *t = NULL;
1178 p = udev_list_entry_get_name(item);
1180 t = strappend(p, "/uevent");
1184 write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
1190 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1191 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1192 _cleanup_free_ char *rule = NULL, *file = NULL;
1193 const char *id_for_seat;
1200 d = udev_device_new_from_syspath(m->udev, sysfs);
1204 if (!udev_device_has_tag(d, "seat"))
1207 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1211 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1214 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1217 mkdir_p_label("/etc/udev/rules.d", 0755);
1218 mac_selinux_init("/etc");
1219 r = write_string_file_atomic_label(file, rule);
1223 return trigger_device(m, d);
1226 static int flush_devices(Manager *m) {
1227 _cleanup_closedir_ DIR *d;
1231 d = opendir("/etc/udev/rules.d");
1233 if (errno != ENOENT)
1234 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1238 while ((de = readdir(d))) {
1240 if (!dirent_is_file(de))
1243 if (!startswith(de->d_name, "72-seat-"))
1246 if (!endswith(de->d_name, ".rules"))
1249 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1250 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1254 return trigger_device(m, NULL);
1257 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1258 const char *sysfs, *seat;
1259 Manager *m = userdata;
1265 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1269 if (!path_startswith(sysfs, "/sys"))
1270 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1272 if (!seat_name_is_valid(seat))
1273 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1275 r = bus_verify_polkit_async(
1278 "org.freedesktop.login1.attach-device",
1282 &m->polkit_registry,
1287 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1289 r = attach_device(m, seat, sysfs);
1293 return sd_bus_reply_method_return(message, NULL);
1296 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1297 Manager *m = userdata;
1303 r = sd_bus_message_read(message, "b", &interactive);
1307 r = bus_verify_polkit_async(
1310 "org.freedesktop.login1.flush-devices",
1314 &m->polkit_registry,
1319 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1321 r = flush_devices(m);
1325 return sd_bus_reply_method_return(message, NULL);
1328 static int have_multiple_sessions(
1337 /* Check for other users' sessions. Greeter sessions do not
1338 * count, and non-login sessions do not count either. */
1339 HASHMAP_FOREACH(session, m->sessions, i)
1340 if (session->class == SESSION_USER &&
1341 session->user->uid != uid)
1347 static int bus_manager_log_shutdown(
1350 HandleAction action) {
1356 if (w != INHIBIT_SHUTDOWN)
1360 case HANDLE_POWEROFF:
1361 p = "MESSAGE=System is powering down.";
1362 q = "SHUTDOWN=power-off";
1365 p = "MESSAGE=System is halting.";
1366 q = "SHUTDOWN=halt";
1369 p = "MESSAGE=System is rebooting.";
1370 q = "SHUTDOWN=reboot";
1373 p = "MESSAGE=System is rebooting with kexec.";
1374 q = "SHUTDOWN=kexec";
1377 p = "MESSAGE=System is shutting down.";
1381 if (!isempty(m->wall_message))
1382 p = strjoina(p, " (", m->wall_message, ")");
1384 return log_struct(LOG_NOTICE,
1385 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1391 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1392 Manager *m = userdata;
1397 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1401 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1406 if (until <= now(CLOCK_MONOTONIC))
1409 /* We want to ignore the lid switch for a while after each
1410 * suspend, and after boot-up. Hence let's install a timer for
1411 * this. As long as the event source exists we ignore the lid
1414 if (m->lid_switch_ignore_event_source) {
1417 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1424 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1426 r = sd_event_add_time(
1428 &m->lid_switch_ignore_event_source,
1431 lid_switch_ignore_handler, m);
1436 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1438 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1439 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1440 [INHIBIT_SLEEP] = "PrepareForSleep"
1443 int active = _active;
1447 assert(w < _INHIBIT_WHAT_MAX);
1448 assert(signal_name[w]);
1450 return sd_bus_emit_signal(m->bus,
1451 "/org/freedesktop/login1",
1452 "org.freedesktop.login1.Manager",
1458 static int execute_shutdown_or_sleep(
1461 HandleAction action,
1462 sd_bus_error *error) {
1464 /// elogind does not need these, we do it ourselves
1466 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1474 assert(w < _INHIBIT_WHAT_MAX);
1476 bus_manager_log_shutdown(m, w, action);
1478 /// elogind does it directly without depending on systemd running the system
1480 r = sd_bus_call_method(
1482 "org.freedesktop.systemd1",
1483 "/org/freedesktop/systemd1",
1484 "org.freedesktop.systemd1.Manager",
1488 "ss", NULL, "replace-irreversibly");
1490 r = shutdown_or_sleep(m, action);
1495 /// elogind neither needs a dbus reply, nor supports systemd action jobs
1497 r = sd_bus_message_read(reply, "o", &p);
1505 m->action_unit = unit_name;
1506 free(m->action_job);
1511 if (w == INHIBIT_SLEEP)
1512 /* And we're back. */
1513 send_prepare_for(m, w, false);
1517 /* Make sure the lid switch is ignored for a while */
1518 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1523 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1525 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1526 Inhibitor *offending = NULL;
1531 if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
1534 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1535 _cleanup_free_ char *comm = NULL, *u = NULL;
1540 (void) get_process_comm(offending->pid, &comm);
1541 u = uid_to_name(offending->uid);
1543 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1544 offending->uid, strna(u),
1545 offending->pid, strna(comm));
1548 /* Actually do the operation */
1549 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
1551 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1553 manager->pending_action = HANDLE_IGNORE;
1554 manager->action_what = 0;
1561 static int manager_inhibit_timeout_handler(
1566 Manager *manager = userdata;
1570 assert(manager->inhibit_timeout_source == s);
1572 r = manager_dispatch_delayed(manager, true);
1573 return (r < 0) ? r : 0;
1576 static int delay_shutdown_or_sleep(
1579 HandleAction action) {
1586 assert(w < _INHIBIT_WHAT_MAX);
1588 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1590 if (m->inhibit_timeout_source) {
1591 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1593 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1595 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1597 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1599 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1600 timeout_val, 0, manager_inhibit_timeout_handler, m);
1605 m->pending_action = action;
1611 int bus_manager_shutdown_or_sleep_now_or_later(
1613 HandleAction action,
1615 sd_bus_error *error) {
1622 assert(w <= _INHIBIT_WHAT_MAX);
1624 /* Tell everybody to prepare for shutdown/sleep */
1625 send_prepare_for(m, w, true);
1628 m->inhibit_delay_max > 0 &&
1629 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1632 /* Shutdown is delayed, keep in mind what we
1633 * want to do, and start a timeout */
1634 r = delay_shutdown_or_sleep(m, w, action);
1636 /* Shutdown is not delayed, execute it
1638 r = execute_shutdown_or_sleep(m, w, action, error);
1643 static int verify_shutdown_creds(
1645 sd_bus_message *message,
1649 const char *action_multiple_sessions,
1650 const char *action_ignore_inhibit,
1651 sd_bus_error *error) {
1653 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1654 bool multiple_sessions, blocked;
1661 assert(w <= _INHIBIT_WHAT_MAX);
1663 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1667 r = sd_bus_creds_get_euid(creds, &uid);
1671 r = have_multiple_sessions(m, uid);
1675 multiple_sessions = r > 0;
1676 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1678 if (multiple_sessions && action_multiple_sessions) {
1679 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1683 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1686 if (blocked && action_ignore_inhibit) {
1687 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1691 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1694 if (!multiple_sessions && !blocked && action) {
1695 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1699 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1705 static int method_do_shutdown_or_sleep(
1707 sd_bus_message *message,
1708 HandleAction sleep_action,
1711 const char *action_multiple_sessions,
1712 const char *action_ignore_inhibit,
1713 const char *sleep_verb,
1714 sd_bus_error *error) {
1721 assert(w <= _INHIBIT_WHAT_MAX);
1723 r = sd_bus_message_read(message, "b", &interactive);
1727 /* Don't allow multiple jobs being executed at the same time */
1729 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1732 r = can_sleep(sleep_verb);
1737 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1740 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1741 action_ignore_inhibit, error);
1745 r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
1749 return sd_bus_reply_method_return(message, NULL);
1752 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1753 Manager *m = userdata;
1755 return method_do_shutdown_or_sleep(
1759 "org.freedesktop.login1.power-off",
1760 "org.freedesktop.login1.power-off-multiple-sessions",
1761 "org.freedesktop.login1.power-off-ignore-inhibit",
1766 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1767 Manager *m = userdata;
1769 return method_do_shutdown_or_sleep(
1773 "org.freedesktop.login1.reboot",
1774 "org.freedesktop.login1.reboot-multiple-sessions",
1775 "org.freedesktop.login1.reboot-ignore-inhibit",
1780 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1781 Manager *m = userdata;
1783 return method_do_shutdown_or_sleep(
1787 "org.freedesktop.login1.suspend",
1788 "org.freedesktop.login1.suspend-multiple-sessions",
1789 "org.freedesktop.login1.suspend-ignore-inhibit",
1794 static int nologin_timeout_handler(
1799 Manager *m = userdata;
1802 log_info("Creating /run/nologin, blocking further logins...");
1804 r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
1806 log_error_errno(r, "Failed to create /run/nologin: %m");
1808 m->unlink_nologin = true;
1813 static int update_schedule_file(Manager *m) {
1814 _cleanup_free_ char *temp_path = NULL;
1815 _cleanup_fclose_ FILE *f = NULL;
1820 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1822 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1824 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1826 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1828 (void) fchmod(fileno(f), 0644);
1834 m->scheduled_shutdown_timeout,
1835 m->enable_wall_messages,
1836 m->scheduled_shutdown_type);
1838 if (!isempty(m->wall_message)) {
1839 _cleanup_free_ char *t;
1841 t = cescape(m->wall_message);
1847 fprintf(f, "WALL_MESSAGE=%s\n", t);
1850 r = fflush_and_check(f);
1854 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1862 (void) unlink(temp_path);
1863 (void) unlink("/run/systemd/shutdown/scheduled");
1865 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
1868 static int manager_scheduled_shutdown_handler(
1873 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1874 Manager *m = userdata;
1875 HandleAction action;
1880 if (isempty(m->scheduled_shutdown_type))
1883 if (streq(m->scheduled_shutdown_type, "halt"))
1884 action = HANDLE_HALT;
1885 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1886 action = HANDLE_POWEROFF;
1888 action = HANDLE_REBOOT;
1890 r = execute_shutdown_or_sleep(m, 0, action, &error);
1892 return log_error_errno(r, "Unable to execute transition to %s: %m", m->scheduled_shutdown_type);
1897 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1898 Manager *m = userdata;
1899 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1900 const char *action_multiple_sessions = NULL;
1901 const char *action_ignore_inhibit = NULL;
1902 const char *action = NULL;
1910 r = sd_bus_message_read(message, "st", &type, &elapse);
1914 if (streq(type, "reboot")) {
1915 action = "org.freedesktop.login1.reboot";
1916 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1917 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1918 } else if (streq(type, "halt")) {
1919 action = "org.freedesktop.login1.halt";
1920 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1921 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1922 } else if (streq(type, "poweroff")) {
1923 action = "org.freedesktop.login1.poweroff";
1924 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1925 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1927 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1929 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1930 action, action_multiple_sessions, action_ignore_inhibit, error);
1934 if (m->scheduled_shutdown_timeout_source) {
1935 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1937 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1939 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
1941 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1943 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
1944 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
1946 return log_error_errno(r, "sd_event_add_time() failed: %m");
1949 r = free_and_strdup(&m->scheduled_shutdown_type, type);
1951 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1955 if (m->nologin_timeout_source) {
1956 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
1958 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1960 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
1962 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1964 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
1965 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
1967 return log_error_errno(r, "sd_event_add_time() failed: %m");
1970 m->scheduled_shutdown_timeout = elapse;
1972 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1976 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
1977 (void) sd_bus_creds_get_tty(creds, &tty);
1979 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
1981 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1986 r = manager_setup_wall_message_timer(m);
1990 if (!isempty(type)) {
1991 r = update_schedule_file(m);
1995 (void) unlink("/run/systemd/shutdown/scheduled");
1997 return sd_bus_reply_method_return(message, NULL);
2000 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2001 Manager *m = userdata;
2007 cancelled = m->scheduled_shutdown_type != NULL;
2009 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2010 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2011 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2012 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2013 m->scheduled_shutdown_timeout = 0;
2015 if (m->unlink_nologin) {
2016 (void) unlink("/run/nologin");
2017 m->unlink_nologin = false;
2021 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2022 const char *tty = NULL;
2026 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2028 (void) sd_bus_creds_get_uid(creds, &uid);
2029 (void) sd_bus_creds_get_tty(creds, &tty);
2032 utmp_wall("The system shutdown has been cancelled",
2033 lookup_uid(uid), tty, logind_wall_tty_filter, m);
2036 return sd_bus_reply_method_return(message, "b", cancelled);
2039 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2040 Manager *m = userdata;
2042 return method_do_shutdown_or_sleep(
2046 "org.freedesktop.login1.hibernate",
2047 "org.freedesktop.login1.hibernate-multiple-sessions",
2048 "org.freedesktop.login1.hibernate-ignore-inhibit",
2053 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2054 Manager *m = userdata;
2056 return method_do_shutdown_or_sleep(
2058 HANDLE_HYBRID_SLEEP,
2060 "org.freedesktop.login1.hibernate",
2061 "org.freedesktop.login1.hibernate-multiple-sessions",
2062 "org.freedesktop.login1.hibernate-ignore-inhibit",
2067 static int method_can_shutdown_or_sleep(
2069 sd_bus_message *message,
2072 const char *action_multiple_sessions,
2073 const char *action_ignore_inhibit,
2074 const char *sleep_verb,
2075 sd_bus_error *error) {
2077 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2078 bool multiple_sessions, challenge, blocked;
2079 const char *result = NULL;
2086 assert(w <= _INHIBIT_WHAT_MAX);
2088 assert(action_multiple_sessions);
2089 assert(action_ignore_inhibit);
2092 r = can_sleep(sleep_verb);
2096 return sd_bus_reply_method_return(message, "s", "na");
2099 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2103 r = sd_bus_creds_get_euid(creds, &uid);
2107 r = have_multiple_sessions(m, uid);
2111 multiple_sessions = r > 0;
2112 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2114 if (multiple_sessions) {
2115 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2122 result = "challenge";
2128 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2132 if (r > 0 && !result)
2134 else if (challenge && (!result || streq(result, "yes")))
2135 result = "challenge";
2140 if (!multiple_sessions && !blocked) {
2141 /* If neither inhibit nor multiple sessions
2142 * apply then just check the normal policy */
2144 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2151 result = "challenge";
2156 return sd_bus_reply_method_return(message, "s", result);
2159 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2160 Manager *m = userdata;
2162 return method_can_shutdown_or_sleep(
2165 "org.freedesktop.login1.power-off",
2166 "org.freedesktop.login1.power-off-multiple-sessions",
2167 "org.freedesktop.login1.power-off-ignore-inhibit",
2172 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2173 Manager *m = userdata;
2175 return method_can_shutdown_or_sleep(
2178 "org.freedesktop.login1.reboot",
2179 "org.freedesktop.login1.reboot-multiple-sessions",
2180 "org.freedesktop.login1.reboot-ignore-inhibit",
2185 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2186 Manager *m = userdata;
2188 return method_can_shutdown_or_sleep(
2191 "org.freedesktop.login1.suspend",
2192 "org.freedesktop.login1.suspend-multiple-sessions",
2193 "org.freedesktop.login1.suspend-ignore-inhibit",
2198 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2199 Manager *m = userdata;
2201 return method_can_shutdown_or_sleep(
2204 "org.freedesktop.login1.hibernate",
2205 "org.freedesktop.login1.hibernate-multiple-sessions",
2206 "org.freedesktop.login1.hibernate-ignore-inhibit",
2211 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2212 Manager *m = userdata;
2214 return method_can_shutdown_or_sleep(
2217 "org.freedesktop.login1.hibernate",
2218 "org.freedesktop.login1.hibernate-multiple-sessions",
2219 "org.freedesktop.login1.hibernate-ignore-inhibit",
2224 static int property_get_reboot_to_firmware_setup(
2227 const char *interface,
2228 const char *property,
2229 sd_bus_message *reply,
2231 sd_bus_error *error) {
2238 r = efi_get_reboot_to_firmware();
2239 if (r < 0 && r != -EOPNOTSUPP)
2242 return sd_bus_message_append(reply, "b", r > 0);
2245 static int method_set_reboot_to_firmware_setup(
2246 sd_bus_message *message,
2248 sd_bus_error *error) {
2251 Manager *m = userdata;
2256 r = sd_bus_message_read(message, "b", &b);
2260 r = bus_verify_polkit_async(message,
2262 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2266 &m->polkit_registry,
2271 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2273 r = efi_set_reboot_to_firmware(b);
2277 return sd_bus_reply_method_return(message, NULL);
2280 static int method_can_reboot_to_firmware_setup(
2281 sd_bus_message *message,
2283 sd_bus_error *error) {
2288 Manager *m = userdata;
2293 r = efi_reboot_to_firmware_supported();
2294 if (r == -EOPNOTSUPP)
2295 return sd_bus_reply_method_return(message, "s", "na");
2299 r = bus_test_polkit(message,
2301 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2312 result = "challenge";
2316 return sd_bus_reply_method_return(message, "s", result);
2319 static int method_set_wall_message(
2320 sd_bus_message *message,
2322 sd_bus_error *error) {
2325 Manager *m = userdata;
2327 int enable_wall_messages;
2332 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2336 r = bus_verify_polkit_async(message,
2338 "org.freedesktop.login1.set-wall-message",
2342 &m->polkit_registry,
2347 return 1; /* Will call us back */
2349 if (isempty(wall_message))
2350 m->wall_message = mfree(m->wall_message);
2352 r = free_and_strdup(&m->wall_message, wall_message);
2357 m->enable_wall_messages = enable_wall_messages;
2359 return sd_bus_reply_method_return(message, NULL);
2362 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2363 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2364 const char *who, *why, *what, *mode;
2365 _cleanup_free_ char *id = NULL;
2366 _cleanup_close_ int fifo_fd = -1;
2367 Manager *m = userdata;
2368 Inhibitor *i = NULL;
2378 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2382 w = inhibit_what_from_string(what);
2384 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2386 mm = inhibit_mode_from_string(mode);
2388 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2390 /* Delay is only supported for shutdown/sleep */
2391 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2392 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2394 /* Don't allow taking delay locks while we are already
2395 * executing the operation. We shouldn't create the impression
2396 * that the lock was successful if the machine is about to go
2397 * down/suspend any moment. */
2398 if (m->action_what & w)
2399 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2401 r = bus_verify_polkit_async(
2404 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2405 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2406 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2407 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2408 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2409 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2410 "org.freedesktop.login1.inhibit-handle-lid-switch",
2414 &m->polkit_registry,
2419 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2421 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2425 r = sd_bus_creds_get_euid(creds, &uid);
2429 r = sd_bus_creds_get_pid(creds, &pid);
2436 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2439 } while (hashmap_get(m->inhibitors, id));
2441 r = manager_add_inhibitor(m, id, &i);
2449 i->why = strdup(why);
2450 i->who = strdup(who);
2452 if (!i->why || !i->who) {
2457 fifo_fd = inhibitor_create_fifo(i);
2465 return sd_bus_reply_method_return(message, "h", fifo_fd);
2474 const sd_bus_vtable manager_vtable[] = {
2475 SD_BUS_VTABLE_START(0),
2477 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2478 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2480 // SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2481 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2482 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2483 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2484 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2485 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2486 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2487 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2488 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2489 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2490 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2491 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2492 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2493 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2494 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2495 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2496 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2497 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2498 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2499 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2500 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2501 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2502 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2504 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2505 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2506 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2507 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2508 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2509 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2510 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2511 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2512 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2513 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2514 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2515 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2516 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2517 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2518 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2519 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2520 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2521 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2522 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2523 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2524 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2525 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2526 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2527 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2528 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2529 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2530 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2531 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2532 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2533 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2534 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2535 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2536 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2537 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2538 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2539 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2540 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2541 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2542 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2543 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2544 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2546 SD_BUS_SIGNAL("SessionNew", "so", 0),
2547 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2548 SD_BUS_SIGNAL("UserNew", "uo", 0),
2549 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2550 SD_BUS_SIGNAL("SeatNew", "so", 0),
2551 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2552 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2553 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2558 /// UNNEEDED by elogind
2560 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2569 if (streq(result, "done"))
2570 r = session_send_create_reply(s, NULL);
2572 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2574 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2575 r = session_send_create_reply(s, &e);
2581 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2582 const char *path, *result, *unit;
2583 Manager *m = userdata;
2592 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2594 bus_log_parse_error(r);
2598 if (m->action_job && streq(m->action_job, path)) {
2599 log_info("Operation finished.");
2601 /* Tell people that they now may take a lock again */
2602 send_prepare_for(m, m->action_what, false);
2604 m->action_job = mfree(m->action_job);
2605 m->action_unit = NULL;
2610 session = hashmap_get(m->session_units, unit);
2613 if (streq_ptr(path, session->scope_job))
2614 session->scope_job = mfree(session->scope_job);
2616 session_jobs_reply(session, unit, result);
2618 session_save(session);
2619 user_save(session->user);
2620 session_add_to_gc_queue(session);
2623 user = hashmap_get(m->user_units, unit);
2626 if (streq_ptr(path, user->service_job))
2627 user->service_job = mfree(user->service_job);
2629 if (streq_ptr(path, user->slice_job))
2630 user->slice_job = mfree(user->slice_job);
2632 LIST_FOREACH(sessions_by_user, session, user->sessions)
2633 session_jobs_reply(session, unit, result);
2636 user_add_to_gc_queue(user);
2642 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2643 const char *path, *unit;
2644 Manager *m = userdata;
2652 r = sd_bus_message_read(message, "so", &unit, &path);
2654 bus_log_parse_error(r);
2658 session = hashmap_get(m->session_units, unit);
2660 session_add_to_gc_queue(session);
2662 user = hashmap_get(m->user_units, unit);
2664 user_add_to_gc_queue(user);
2669 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2670 _cleanup_free_ char *unit = NULL;
2671 Manager *m = userdata;
2680 path = sd_bus_message_get_path(message);
2684 r = unit_name_from_dbus_path(path, &unit);
2685 if (r == -EINVAL) /* not a unit */
2692 session = hashmap_get(m->session_units, unit);
2694 session_add_to_gc_queue(session);
2696 user = hashmap_get(m->user_units, unit);
2698 user_add_to_gc_queue(user);
2703 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2704 Manager *m = userdata;
2712 r = sd_bus_message_read(message, "b", &b);
2714 bus_log_parse_error(r);
2721 /* systemd finished reloading, let's recheck all our sessions */
2722 log_debug("System manager has been reloaded, rechecking sessions...");
2724 HASHMAP_FOREACH(session, m->sessions, i)
2725 session_add_to_gc_queue(session);
2731 int manager_send_changed(Manager *manager, const char *property, ...) {
2736 l = strv_from_stdarg_alloca(property);
2738 return sd_bus_emit_properties_changed_strv(
2740 "/org/freedesktop/login1",
2741 "org.freedesktop.login1.Manager",
2745 /// UNNEEDED by elogind
2747 int manager_start_scope(
2752 const char *description,
2753 const char *after, const char *after2,
2754 sd_bus_error *error,
2757 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2764 r = sd_bus_message_new_method_call(
2767 "org.freedesktop.systemd1",
2768 "/org/freedesktop/systemd1",
2769 "org.freedesktop.systemd1.Manager",
2770 "StartTransientUnit");
2774 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2778 r = sd_bus_message_open_container(m, 'a', "(sv)");
2782 if (!isempty(slice)) {
2783 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2788 if (!isempty(description)) {
2789 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2794 if (!isempty(after)) {
2795 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2800 if (!isempty(after2)) {
2801 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2806 /* cgroup empty notification is not available in containers
2807 * currently. To make this less problematic, let's shorten the
2808 * stop timeout for sessions, so that we don't wait
2811 /* Make sure that the session shells are terminated with
2812 * SIGHUP since bash and friends tend to ignore SIGTERM */
2813 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2817 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2821 r = sd_bus_message_close_container(m);
2825 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2829 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2837 r = sd_bus_message_read(reply, "o", &j);
2851 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2852 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2858 r = sd_bus_call_method(
2860 "org.freedesktop.systemd1",
2861 "/org/freedesktop/systemd1",
2862 "org.freedesktop.systemd1.Manager",
2866 "ss", unit, "fail");
2874 r = sd_bus_message_read(reply, "o", &j);
2888 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2889 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2895 r = sd_bus_call_method(
2897 "org.freedesktop.systemd1",
2898 "/org/freedesktop/systemd1",
2899 "org.freedesktop.systemd1.Manager",
2903 "ss", unit, "fail");
2905 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2906 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2911 sd_bus_error_free(error);
2922 r = sd_bus_message_read(reply, "o", &j);
2936 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2937 _cleanup_free_ char *path = NULL;
2943 path = unit_dbus_path_from_name(scope);
2947 r = sd_bus_call_method(
2949 "org.freedesktop.systemd1",
2951 "org.freedesktop.systemd1.Scope",
2957 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2958 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2959 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2960 sd_bus_error_free(error);
2970 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2974 return sd_bus_call_method(
2976 "org.freedesktop.systemd1",
2977 "/org/freedesktop/systemd1",
2978 "org.freedesktop.systemd1.Manager",
2982 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2985 int manager_unit_is_active(Manager *manager, const char *unit) {
2986 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2987 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2988 _cleanup_free_ char *path = NULL;
2995 path = unit_dbus_path_from_name(unit);
2999 r = sd_bus_get_property(
3001 "org.freedesktop.systemd1",
3003 "org.freedesktop.systemd1.Unit",
3009 /* systemd might have droppped off momentarily, let's
3010 * not make this an error */
3011 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3012 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3015 /* If the unit is already unloaded then it's not
3017 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3018 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3024 r = sd_bus_message_read(reply, "s", &state);
3028 return !streq(state, "inactive") && !streq(state, "failed");
3031 int manager_job_is_active(Manager *manager, const char *path) {
3032 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3033 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3039 r = sd_bus_get_property(
3041 "org.freedesktop.systemd1",
3043 "org.freedesktop.systemd1.Job",
3049 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3050 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3053 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3059 /* We don't actually care about the state really. The fact
3060 * that we could read the job state is enough for us */