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 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
44 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
53 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
57 r = sd_bus_creds_get_session(creds, &name);
62 session = hashmap_get(m->sessions, name);
64 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
70 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
78 if (uid == UID_INVALID) {
79 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
81 /* Note that we get the owner UID of the session, not the actual client UID here! */
82 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
86 r = sd_bus_creds_get_owner_uid(creds, &uid);
91 user = hashmap_get(m->users, UID_TO_PTR(uid));
93 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
99 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
110 r = manager_get_session_from_creds(m, message, NULL, error, &session);
114 seat = session->seat;
117 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
119 seat = hashmap_get(m->seats, name);
121 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
128 static int property_get_idle_hint(
131 const char *interface,
132 const char *property,
133 sd_bus_message *reply,
135 sd_bus_error *error) {
137 Manager *m = userdata;
143 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
146 static int property_get_idle_since_hint(
149 const char *interface,
150 const char *property,
151 sd_bus_message *reply,
153 sd_bus_error *error) {
155 Manager *m = userdata;
162 manager_get_idle_hint(m, &t);
164 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
167 static int property_get_inhibited(
170 const char *interface,
171 const char *property,
172 sd_bus_message *reply,
174 sd_bus_error *error) {
176 Manager *m = userdata;
183 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
185 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
188 static int property_get_preparing(
191 const char *interface,
192 const char *property,
193 sd_bus_message *reply,
195 sd_bus_error *error) {
197 Manager *m = userdata;
204 if (streq(property, "PreparingForShutdown"))
205 b = !!(m->action_what & INHIBIT_SHUTDOWN);
207 b = !!(m->action_what & INHIBIT_SLEEP);
209 return sd_bus_message_append(reply, "b", b);
212 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
214 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
215 _cleanup_free_ char *p = NULL;
216 Manager *m = userdata;
225 r = sd_bus_message_read(message, "s", &name);
229 r = manager_get_session_from_creds(m, message, name, error, &session);
233 p = session_bus_path(session);
237 return sd_bus_reply_method_return(message, "o", p);
240 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
241 _cleanup_free_ char *p = NULL;
242 Session *session = NULL;
243 Manager *m = userdata;
251 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
253 r = sd_bus_message_read(message, "u", &pid);
258 r = manager_get_session_from_creds(m, message, NULL, error, &session);
262 r = manager_get_session_by_pid(m, pid, &session);
267 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
270 p = session_bus_path(session);
274 return sd_bus_reply_method_return(message, "o", p);
277 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
278 _cleanup_free_ char *p = NULL;
279 Manager *m = userdata;
288 r = sd_bus_message_read(message, "u", &uid);
292 r = manager_get_user_from_creds(m, message, uid, error, &user);
296 p = user_bus_path(user);
300 return sd_bus_reply_method_return(message, "o", p);
303 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
304 _cleanup_free_ char *p = NULL;
305 Manager *m = userdata;
314 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
316 r = sd_bus_message_read(message, "u", &pid);
321 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
325 r = manager_get_user_by_pid(m, pid, &user);
329 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);
332 p = user_bus_path(user);
336 return sd_bus_reply_method_return(message, "o", p);
339 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
340 _cleanup_free_ char *p = NULL;
341 Manager *m = userdata;
350 r = sd_bus_message_read(message, "s", &name);
354 r = manager_get_seat_from_creds(m, message, name, error, &seat);
358 p = seat_bus_path(seat);
362 return sd_bus_reply_method_return(message, "o", p);
365 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
366 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
367 Manager *m = userdata;
376 r = sd_bus_message_new_method_return(message, &reply);
380 r = sd_bus_message_open_container(reply, 'a', "(susso)");
384 HASHMAP_FOREACH(session, m->sessions, i) {
385 _cleanup_free_ char *p = NULL;
387 p = session_bus_path(session);
391 r = sd_bus_message_append(reply, "(susso)",
393 (uint32_t) session->user->uid,
395 session->seat ? session->seat->id : "",
401 r = sd_bus_message_close_container(reply);
405 return sd_bus_send(bus, reply, NULL);
408 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
409 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
410 Manager *m = userdata;
419 r = sd_bus_message_new_method_return(message, &reply);
423 r = sd_bus_message_open_container(reply, 'a', "(uso)");
427 HASHMAP_FOREACH(user, m->users, i) {
428 _cleanup_free_ char *p = NULL;
430 p = user_bus_path(user);
434 r = sd_bus_message_append(reply, "(uso)",
435 (uint32_t) user->uid,
442 r = sd_bus_message_close_container(reply);
446 return sd_bus_send(bus, reply, NULL);
449 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
450 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
451 Manager *m = userdata;
460 r = sd_bus_message_new_method_return(message, &reply);
464 r = sd_bus_message_open_container(reply, 'a', "(so)");
468 HASHMAP_FOREACH(seat, m->seats, i) {
469 _cleanup_free_ char *p = NULL;
471 p = seat_bus_path(seat);
475 r = sd_bus_message_append(reply, "(so)", seat->id, p);
480 r = sd_bus_message_close_container(reply);
484 return sd_bus_send(bus, reply, NULL);
487 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
488 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
489 Manager *m = userdata;
490 Inhibitor *inhibitor;
494 r = sd_bus_message_new_method_return(message, &reply);
498 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
502 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
504 r = sd_bus_message_append(reply, "(ssssuu)",
505 strempty(inhibit_what_to_string(inhibitor->what)),
506 strempty(inhibitor->who),
507 strempty(inhibitor->why),
508 strempty(inhibit_mode_to_string(inhibitor->mode)),
509 (uint32_t) inhibitor->uid,
510 (uint32_t) inhibitor->pid);
515 r = sd_bus_message_close_container(reply);
519 return sd_bus_send(bus, reply, NULL);
522 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
523 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
524 uint32_t uid, leader, audit_id = 0;
525 _cleanup_free_ char *id = NULL;
526 Session *session = NULL;
527 Manager *m = userdata;
540 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
545 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
548 t = _SESSION_TYPE_INVALID;
550 t = session_type_from_string(type);
552 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
556 c = _SESSION_CLASS_INVALID;
558 c = session_class_from_string(class);
560 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
563 if (isempty(desktop))
566 if (!string_is_safe(desktop))
567 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
573 seat = hashmap_get(m->seats, cseat);
575 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
578 if (tty_is_vc(tty)) {
583 else if (seat != m->seat0)
584 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);
586 v = vtnr_from_tty(tty);
588 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
592 else if (vtnr != (uint32_t) v)
593 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
595 } else if (tty_is_console(tty)) {
599 else if (seat != m->seat0)
600 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
603 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
607 if (seat_has_vts(seat)) {
608 if (!vtnr || vtnr > 63)
609 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
612 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
616 r = sd_bus_message_enter_container(message, 'a', "(sv)");
620 if (t == _SESSION_TYPE_INVALID) {
621 if (!isempty(display))
623 else if (!isempty(tty))
626 t = SESSION_UNSPECIFIED;
629 if (c == _SESSION_CLASS_INVALID) {
630 if (t == SESSION_UNSPECIFIED)
631 c = SESSION_BACKGROUND;
637 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
639 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
643 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
648 manager_get_session_by_pid(m, leader, &session);
650 _cleanup_free_ char *path = NULL;
651 _cleanup_close_ int fifo_fd = -1;
653 /* Session already exists, client is probably
654 * something like "su" which changes uid but is still
655 * the same session */
657 fifo_fd = session_create_fifo(session);
661 path = session_bus_path(session);
665 log_debug("Sending reply about an existing session: "
666 "id=%s object_path=%s uid=%u runtime_path=%s "
667 "session_fd=%d seat=%s vtnr=%u",
670 (uint32_t) session->user->uid,
671 session->user->runtime_path,
673 session->seat ? session->seat->id : "",
674 (uint32_t) session->vtnr);
676 return sd_bus_reply_method_return(
680 session->user->runtime_path,
682 (uint32_t) session->user->uid,
683 session->seat ? session->seat->id : "",
684 (uint32_t) session->vtnr,
688 audit_session_from_pid(leader, &audit_id);
690 /* Keep our session IDs and the audit session IDs in sync */
692 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
695 /* Wut? There's already a session by this name and we
696 * didn't find it above? Weird, then let's not trust
697 * the audit data and let's better register a new
699 if (hashmap_get(m->sessions, id)) {
700 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
713 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
716 } while (hashmap_get(m->sessions, id));
719 r = manager_add_user_by_uid(m, uid, &user);
723 r = manager_add_session(m, id, &session);
727 session_set_user(session, user);
729 session->leader = leader;
730 session->audit_id = audit_id;
733 session->remote = remote;
734 session->vtnr = vtnr;
737 session->tty = strdup(tty);
744 if (!isempty(display)) {
745 session->display = strdup(display);
746 if (!session->display) {
752 if (!isempty(remote_user)) {
753 session->remote_user = strdup(remote_user);
754 if (!session->remote_user) {
760 if (!isempty(remote_host)) {
761 session->remote_host = strdup(remote_host);
762 if (!session->remote_host) {
768 if (!isempty(service)) {
769 session->service = strdup(service);
770 if (!session->service) {
776 if (!isempty(desktop)) {
777 session->desktop = strdup(desktop);
778 if (!session->desktop) {
785 r = seat_attach_session(seat, session);
790 r = session_start(session);
794 session->create_message = sd_bus_message_ref(message);
796 /* Here upstream systemd starts cgroups and the user systemd,
797 and arranges to reply asynchronously. We reply
800 r = session_send_create_reply(session, NULL);
804 session_save(session);
810 session_add_to_gc_queue(session);
813 user_add_to_gc_queue(user);
818 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
819 Manager *m = userdata;
828 r = sd_bus_message_read(message, "s", &name);
832 r = manager_get_session_from_creds(m, message, name, error, &session);
836 r = session_release(session);
840 return sd_bus_reply_method_return(message, NULL);
843 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
844 Manager *m = userdata;
853 r = sd_bus_message_read(message, "s", &name);
857 r = manager_get_session_from_creds(m, message, name, error, &session);
861 return bus_session_method_activate(bus, message, session, error);
864 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
865 const char *session_name, *seat_name;
866 Manager *m = userdata;
875 /* Same as ActivateSession() but refuses to work if
876 * the seat doesn't match */
878 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
882 r = manager_get_session_from_creds(m, message, session_name, error, &session);
886 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
890 if (session->seat != seat)
891 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
893 r = session_activate(session);
897 return sd_bus_reply_method_return(message, NULL);
900 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
901 Manager *m = userdata;
910 r = sd_bus_message_read(message, "s", &name);
914 r = manager_get_session_from_creds(m, message, name, error, &session);
918 return bus_session_method_lock(bus, message, session, error);
921 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
922 Manager *m = userdata;
929 r = bus_verify_polkit_async(
932 "org.freedesktop.login1.lock-sessions",
940 return 1; /* Will call us back */
942 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
946 return sd_bus_reply_method_return(message, NULL);
949 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
951 Manager *m = userdata;
959 r = sd_bus_message_read(message, "s", &name);
963 r = manager_get_session_from_creds(m, message, name, error, &session);
967 return bus_session_method_kill(bus, message, session, error);
970 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
971 Manager *m = userdata;
980 r = sd_bus_message_read(message, "u", &uid);
984 r = manager_get_user_from_creds(m, message, uid, error, &user);
988 return bus_user_method_kill(bus, message, user, error);
991 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
992 Manager *m = userdata;
1001 r = sd_bus_message_read(message, "s", &name);
1005 r = manager_get_session_from_creds(m, message, name, error, &session);
1009 return bus_session_method_terminate(bus, message, session, error);
1012 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1013 Manager *m = userdata;
1022 r = sd_bus_message_read(message, "u", &uid);
1026 r = manager_get_user_from_creds(m, message, uid, error, &user);
1030 return bus_user_method_terminate(bus, message, user, error);
1033 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1034 Manager *m = userdata;
1043 r = sd_bus_message_read(message, "s", &name);
1047 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1051 return bus_seat_method_terminate(bus, message, seat, error);
1054 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1055 _cleanup_free_ char *cc = NULL;
1056 Manager *m = userdata;
1067 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1071 if (uid == UID_INVALID) {
1072 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1074 /* Note that we get the owner UID of the session, not the actual client UID here! */
1075 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1079 r = sd_bus_creds_get_owner_uid(creds, &uid);
1087 return errno ? -errno : -ENOENT;
1089 r = bus_verify_polkit_async(
1092 "org.freedesktop.login1.set-user-linger",
1095 &m->polkit_registry,
1100 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1102 mkdir_p_label("/var/lib/systemd", 0755);
1104 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1108 cc = cescape(pw->pw_name);
1112 path = strjoina("/var/lib/systemd/linger/", cc);
1120 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1127 if (r < 0 && errno != ENOENT)
1130 u = hashmap_get(m->users, UID_TO_PTR(uid));
1132 user_add_to_gc_queue(u);
1135 return sd_bus_reply_method_return(message, NULL);
1138 static int trigger_device(Manager *m, struct udev_device *d) {
1139 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1140 struct udev_list_entry *first, *item;
1145 e = udev_enumerate_new(m->udev);
1150 r = udev_enumerate_add_match_parent(e, d);
1155 r = udev_enumerate_scan_devices(e);
1159 first = udev_enumerate_get_list_entry(e);
1160 udev_list_entry_foreach(item, first) {
1161 _cleanup_free_ char *t = NULL;
1164 p = udev_list_entry_get_name(item);
1166 t = strappend(p, "/uevent");
1170 write_string_file(t, "change");
1176 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1177 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1178 _cleanup_free_ char *rule = NULL, *file = NULL;
1179 const char *id_for_seat;
1186 d = udev_device_new_from_syspath(m->udev, sysfs);
1190 if (!udev_device_has_tag(d, "seat"))
1193 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1197 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1200 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1203 mkdir_p_label("/etc/udev/rules.d", 0755);
1204 mac_selinux_init("/etc");
1205 r = write_string_file_atomic_label(file, rule);
1209 return trigger_device(m, d);
1212 static int flush_devices(Manager *m) {
1213 _cleanup_closedir_ DIR *d;
1217 d = opendir("/etc/udev/rules.d");
1219 if (errno != ENOENT)
1220 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1224 while ((de = readdir(d))) {
1226 if (!dirent_is_file(de))
1229 if (!startswith(de->d_name, "72-seat-"))
1232 if (!endswith(de->d_name, ".rules"))
1235 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1236 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1240 return trigger_device(m, NULL);
1243 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1244 const char *sysfs, *seat;
1245 Manager *m = userdata;
1252 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1256 if (!path_startswith(sysfs, "/sys"))
1257 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1259 if (!seat_name_is_valid(seat))
1260 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1262 r = bus_verify_polkit_async(
1265 "org.freedesktop.login1.attach-device",
1268 &m->polkit_registry,
1273 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1275 r = attach_device(m, seat, sysfs);
1279 return sd_bus_reply_method_return(message, NULL);
1282 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1283 Manager *m = userdata;
1290 r = sd_bus_message_read(message, "b", &interactive);
1294 r = bus_verify_polkit_async(
1297 "org.freedesktop.login1.flush-devices",
1300 &m->polkit_registry,
1305 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1307 r = flush_devices(m);
1311 return sd_bus_reply_method_return(message, NULL);
1314 static int have_multiple_sessions(
1323 /* Check for other users' sessions. Greeter sessions do not
1324 * count, and non-login sessions do not count either. */
1325 HASHMAP_FOREACH(session, m->sessions, i)
1326 if (session->class == SESSION_USER &&
1327 session->user->uid != uid)
1333 static int bus_manager_log_shutdown(
1336 HandleAction action) {
1342 if (w != INHIBIT_SHUTDOWN)
1346 case HANDLE_POWEROFF:
1347 p = "MESSAGE=System is powering down.";
1348 q = "SHUTDOWN=power-off";
1351 p = "MESSAGE=System is halting.";
1352 q = "SHUTDOWN=halt";
1355 p = "MESSAGE=System is rebooting.";
1356 q = "SHUTDOWN=reboot";
1359 p = "MESSAGE=System is rebooting with kexec.";
1360 q = "SHUTDOWN=kexec";
1363 p = "MESSAGE=System is shutting down.";
1368 return log_struct(LOG_NOTICE,
1369 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1375 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1376 Manager *m = userdata;
1381 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1385 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1390 if (until <= now(CLOCK_MONOTONIC))
1393 /* We want to ignore the lid switch for a while after each
1394 * suspend, and after boot-up. Hence let's install a timer for
1395 * this. As long as the event source exists we ignore the lid
1398 if (m->lid_switch_ignore_event_source) {
1401 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1408 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1410 r = sd_event_add_time(
1412 &m->lid_switch_ignore_event_source,
1415 lid_switch_ignore_handler, m);
1420 static int execute_shutdown_or_sleep(
1423 HandleAction action,
1424 sd_bus_error *error) {
1426 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1433 assert(w < _INHIBIT_WHAT_MAX);
1435 bus_manager_log_shutdown(m, w, action);
1437 /* FIXME: here do the thing. */
1439 r = sd_bus_call_method(
1441 "org.freedesktop.systemd1",
1442 "/org/freedesktop/systemd1",
1443 "org.freedesktop.systemd1.Manager",
1447 "ss", NULL, "replace-irreversibly");
1451 r = sd_bus_message_read(reply, "o", &p);
1459 /* Make sure the lid switch is ignored for a while (?) */
1460 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1465 static int delay_shutdown_or_sleep(
1468 HandleAction action) {
1472 assert(w < _INHIBIT_WHAT_MAX);
1474 m->action_timestamp = now(CLOCK_MONOTONIC);
1475 m->pending_action = action;
1481 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1483 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1484 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1485 [INHIBIT_SLEEP] = "PrepareForSleep"
1488 int active = _active;
1492 assert(w < _INHIBIT_WHAT_MAX);
1493 assert(signal_name[w]);
1495 return sd_bus_emit_signal(m->bus,
1496 "/org/freedesktop/login1",
1497 "org.freedesktop.login1.Manager",
1503 int bus_manager_shutdown_or_sleep_now_or_later(
1505 HandleAction action,
1507 sd_bus_error *error) {
1514 assert(w <= _INHIBIT_WHAT_MAX);
1516 /* Tell everybody to prepare for shutdown/sleep */
1517 send_prepare_for(m, w, true);
1520 m->inhibit_delay_max > 0 &&
1521 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1524 /* Shutdown is delayed, keep in mind what we
1525 * want to do, and start a timeout */
1526 r = delay_shutdown_or_sleep(m, w, action);
1528 /* Shutdown is not delayed, execute it
1530 r = execute_shutdown_or_sleep(m, w, action, error);
1535 static int method_do_shutdown_or_sleep(
1537 sd_bus_message *message,
1538 HandleAction sleep_action,
1541 const char *action_multiple_sessions,
1542 const char *action_ignore_inhibit,
1543 const char *sleep_verb,
1544 sd_bus_message_handler_t method,
1545 sd_bus_error *error) {
1547 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1548 bool multiple_sessions, blocked;
1555 assert(w <= _INHIBIT_WHAT_MAX);
1557 assert(action_multiple_sessions);
1558 assert(action_ignore_inhibit);
1561 r = sd_bus_message_read(message, "b", &interactive);
1565 /* Don't allow multiple jobs being executed at the same time */
1567 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1570 r = can_sleep(sleep_verb);
1575 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1578 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1582 r = sd_bus_creds_get_euid(creds, &uid);
1586 r = have_multiple_sessions(m, uid);
1590 multiple_sessions = r > 0;
1591 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1593 if (multiple_sessions) {
1594 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1598 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1602 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1606 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1609 if (!multiple_sessions && !blocked) {
1610 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1614 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1617 r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
1621 return sd_bus_reply_method_return(message, NULL);
1624 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1625 Manager *m = userdata;
1627 return method_do_shutdown_or_sleep(
1631 "org.freedesktop.login1.power-off",
1632 "org.freedesktop.login1.power-off-multiple-sessions",
1633 "org.freedesktop.login1.power-off-ignore-inhibit",
1639 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1640 Manager *m = userdata;
1642 return method_do_shutdown_or_sleep(
1646 "org.freedesktop.login1.reboot",
1647 "org.freedesktop.login1.reboot-multiple-sessions",
1648 "org.freedesktop.login1.reboot-ignore-inhibit",
1654 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1655 Manager *m = userdata;
1657 return method_do_shutdown_or_sleep(
1661 "org.freedesktop.login1.suspend",
1662 "org.freedesktop.login1.suspend-multiple-sessions",
1663 "org.freedesktop.login1.suspend-ignore-inhibit",
1669 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1670 Manager *m = userdata;
1672 return method_do_shutdown_or_sleep(
1676 "org.freedesktop.login1.hibernate",
1677 "org.freedesktop.login1.hibernate-multiple-sessions",
1678 "org.freedesktop.login1.hibernate-ignore-inhibit",
1684 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1685 Manager *m = userdata;
1687 return method_do_shutdown_or_sleep(
1689 HANDLE_HYBRID_SLEEP,
1691 "org.freedesktop.login1.hibernate",
1692 "org.freedesktop.login1.hibernate-multiple-sessions",
1693 "org.freedesktop.login1.hibernate-ignore-inhibit",
1695 method_hybrid_sleep,
1699 static int method_can_shutdown_or_sleep(
1701 sd_bus_message *message,
1704 const char *action_multiple_sessions,
1705 const char *action_ignore_inhibit,
1706 const char *sleep_verb,
1707 sd_bus_error *error) {
1709 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1710 bool multiple_sessions, challenge, blocked;
1711 const char *result = NULL;
1718 assert(w <= _INHIBIT_WHAT_MAX);
1720 assert(action_multiple_sessions);
1721 assert(action_ignore_inhibit);
1724 r = can_sleep(sleep_verb);
1728 return sd_bus_reply_method_return(message, "s", "na");
1731 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1735 r = sd_bus_creds_get_euid(creds, &uid);
1739 r = have_multiple_sessions(m, uid);
1743 multiple_sessions = r > 0;
1744 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1746 if (multiple_sessions) {
1747 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, UID_INVALID, &challenge, error);
1754 result = "challenge";
1760 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, UID_INVALID, &challenge, error);
1764 if (r > 0 && !result)
1766 else if (challenge && (!result || streq(result, "yes")))
1767 result = "challenge";
1772 if (!multiple_sessions && !blocked) {
1773 /* If neither inhibit nor multiple sessions
1774 * apply then just check the normal policy */
1776 r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, UID_INVALID, &challenge, error);
1783 result = "challenge";
1788 return sd_bus_reply_method_return(message, "s", result);
1791 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1792 Manager *m = userdata;
1794 return method_can_shutdown_or_sleep(
1797 "org.freedesktop.login1.power-off",
1798 "org.freedesktop.login1.power-off-multiple-sessions",
1799 "org.freedesktop.login1.power-off-ignore-inhibit",
1804 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1805 Manager *m = userdata;
1807 return method_can_shutdown_or_sleep(
1810 "org.freedesktop.login1.reboot",
1811 "org.freedesktop.login1.reboot-multiple-sessions",
1812 "org.freedesktop.login1.reboot-ignore-inhibit",
1817 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1818 Manager *m = userdata;
1820 return method_can_shutdown_or_sleep(
1823 "org.freedesktop.login1.suspend",
1824 "org.freedesktop.login1.suspend-multiple-sessions",
1825 "org.freedesktop.login1.suspend-ignore-inhibit",
1830 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1831 Manager *m = userdata;
1833 return method_can_shutdown_or_sleep(
1836 "org.freedesktop.login1.hibernate",
1837 "org.freedesktop.login1.hibernate-multiple-sessions",
1838 "org.freedesktop.login1.hibernate-ignore-inhibit",
1843 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1844 Manager *m = userdata;
1846 return method_can_shutdown_or_sleep(
1849 "org.freedesktop.login1.hibernate",
1850 "org.freedesktop.login1.hibernate-multiple-sessions",
1851 "org.freedesktop.login1.hibernate-ignore-inhibit",
1856 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1857 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1858 const char *who, *why, *what, *mode;
1859 _cleanup_free_ char *id = NULL;
1860 _cleanup_close_ int fifo_fd = -1;
1861 Manager *m = userdata;
1862 Inhibitor *i = NULL;
1873 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1877 w = inhibit_what_from_string(what);
1879 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1881 mm = inhibit_mode_from_string(mode);
1883 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1885 /* Delay is only supported for shutdown/sleep */
1886 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1887 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1889 /* Don't allow taking delay locks while we are already
1890 * executing the operation. We shouldn't create the impression
1891 * that the lock was successful if the machine is about to go
1892 * down/suspend any moment. */
1893 if (m->action_what & w)
1894 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1896 r = bus_verify_polkit_async(
1899 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1900 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1901 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1902 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1903 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1904 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1905 "org.freedesktop.login1.inhibit-handle-lid-switch",
1908 &m->polkit_registry,
1913 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1915 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
1919 r = sd_bus_creds_get_euid(creds, &uid);
1923 r = sd_bus_creds_get_pid(creds, &pid);
1931 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1934 } while (hashmap_get(m->inhibitors, id));
1936 r = manager_add_inhibitor(m, id, &i);
1944 i->why = strdup(why);
1945 i->who = strdup(who);
1947 if (!i->why || !i->who) {
1952 fifo_fd = inhibitor_create_fifo(i);
1960 return sd_bus_reply_method_return(message, "h", fifo_fd);
1969 const sd_bus_vtable manager_vtable[] = {
1970 SD_BUS_VTABLE_START(0),
1972 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
1973 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
1974 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
1975 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1976 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1977 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1978 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1979 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1980 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
1981 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
1982 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
1983 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
1984 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
1985 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
1986 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1987 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
1988 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1989 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1990 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1992 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
1993 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1994 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
1995 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1996 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1997 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
1998 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
1999 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2000 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2001 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2002 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2003 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2006 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2007 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2008 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2009 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2010 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2011 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2012 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2013 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2014 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2015 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2016 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2017 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2018 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2019 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2020 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2021 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2022 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2023 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2024 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2026 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2027 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2029 SD_BUS_SIGNAL("SessionNew", "so", 0),
2030 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2031 SD_BUS_SIGNAL("UserNew", "uo", 0),
2032 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2033 SD_BUS_SIGNAL("SeatNew", "so", 0),
2034 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2035 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2036 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2041 int manager_send_changed(Manager *manager, const char *property, ...) {
2046 l = strv_from_stdarg_alloca(property);
2048 return sd_bus_emit_properties_changed_strv(
2050 "/org/freedesktop/login1",
2051 "org.freedesktop.login1.Manager",
2055 int manager_dispatch_delayed(Manager *manager) {
2056 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2057 Inhibitor *offending = NULL;
2062 if (manager->action_what == 0)
2065 /* Continue delay? */
2066 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
2067 _cleanup_free_ char *comm = NULL, *u = NULL;
2069 get_process_comm(offending->pid, &comm);
2070 u = uid_to_name(offending->uid);
2072 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2075 log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
2076 offending->uid, strna(u),
2077 offending->pid, strna(comm));
2080 /* Actually do the operation */
2081 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
2083 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2085 manager->pending_action = HANDLE_IGNORE;
2086 manager->action_what = 0;
2093 int manager_start_scope(
2098 const char *description,
2099 const char *after, const char *after2,
2100 sd_bus_error *error,
2103 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2110 r = sd_bus_message_new_method_call(
2113 "org.freedesktop.systemd1",
2114 "/org/freedesktop/systemd1",
2115 "org.freedesktop.systemd1.Manager",
2116 "StartTransientUnit");
2120 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2124 r = sd_bus_message_open_container(m, 'a', "(sv)");
2128 if (!isempty(slice)) {
2129 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2134 if (!isempty(description)) {
2135 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2140 if (!isempty(after)) {
2141 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2146 if (!isempty(after2)) {
2147 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2152 /* cgroup empty notification is not available in containers
2153 * currently. To make this less problematic, let's shorten the
2154 * stop timeout for sessions, so that we don't wait
2157 /* Make sure that the session shells are terminated with
2158 * SIGHUP since bash and friends tend to ignore SIGTERM */
2159 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2163 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2167 r = sd_bus_message_close_container(m);
2171 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2175 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2183 r = sd_bus_message_read(reply, "o", &j);
2197 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2198 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2204 r = sd_bus_call_method(
2206 "org.freedesktop.systemd1",
2207 "/org/freedesktop/systemd1",
2208 "org.freedesktop.systemd1.Manager",
2212 "ss", unit, "fail");
2220 r = sd_bus_message_read(reply, "o", &j);
2234 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2235 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2241 r = sd_bus_call_method(
2243 "org.freedesktop.systemd1",
2244 "/org/freedesktop/systemd1",
2245 "org.freedesktop.systemd1.Manager",
2249 "ss", unit, "fail");
2251 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2252 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2257 sd_bus_error_free(error);
2268 r = sd_bus_message_read(reply, "o", &j);
2282 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2283 _cleanup_free_ char *path = NULL;
2289 path = unit_dbus_path_from_name(scope);
2293 r = sd_bus_call_method(
2295 "org.freedesktop.systemd1",
2297 "org.freedesktop.systemd1.Scope",
2303 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2304 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2305 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2306 sd_bus_error_free(error);
2316 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2320 return sd_bus_call_method(
2322 "org.freedesktop.systemd1",
2323 "/org/freedesktop/systemd1",
2324 "org.freedesktop.systemd1.Manager",
2328 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2331 int manager_unit_is_active(Manager *manager, const char *unit) {
2332 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2333 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2334 _cleanup_free_ char *path = NULL;
2341 path = unit_dbus_path_from_name(unit);
2345 r = sd_bus_get_property(
2347 "org.freedesktop.systemd1",
2349 "org.freedesktop.systemd1.Unit",
2355 /* systemd might have droppped off momentarily, let's
2356 * not make this an error */
2357 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2358 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2361 /* If the unit is already unloaded then it's not
2363 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2364 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2370 r = sd_bus_message_read(reply, "s", &state);
2374 return !streq(state, "inactive") && !streq(state, "failed");
2377 int manager_job_is_active(Manager *manager, const char *path) {
2378 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2379 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2385 r = sd_bus_get_property(
2387 "org.freedesktop.systemd1",
2389 "org.freedesktop.systemd1.Job",
2395 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2396 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2399 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2405 /* We don't actually care about the state really. The fact
2406 * that we could read the job state is enough for us */