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 /* Now, let's wait until the slice unit and stuff got
797 * created. We send the reply back from
798 * session_send_create_reply(). */
800 /* Elogind note: replying directly, since we're not actually
801 starting slices and thus we aren't waiting on systemd. */
803 r = session_send_create_reply(session, NULL);
807 session_save(session);
813 session_add_to_gc_queue(session);
816 user_add_to_gc_queue(user);
821 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
822 Manager *m = userdata;
831 r = sd_bus_message_read(message, "s", &name);
835 r = manager_get_session_from_creds(m, message, name, error, &session);
839 r = session_release(session);
843 return sd_bus_reply_method_return(message, NULL);
846 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
847 Manager *m = userdata;
856 r = sd_bus_message_read(message, "s", &name);
860 r = manager_get_session_from_creds(m, message, name, error, &session);
864 return bus_session_method_activate(bus, message, session, error);
867 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
868 const char *session_name, *seat_name;
869 Manager *m = userdata;
878 /* Same as ActivateSession() but refuses to work if
879 * the seat doesn't match */
881 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
885 r = manager_get_session_from_creds(m, message, session_name, error, &session);
889 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
893 if (session->seat != seat)
894 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
896 r = session_activate(session);
900 return sd_bus_reply_method_return(message, NULL);
903 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
904 Manager *m = userdata;
913 r = sd_bus_message_read(message, "s", &name);
917 r = manager_get_session_from_creds(m, message, name, error, &session);
921 return bus_session_method_lock(bus, message, session, error);
924 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
925 Manager *m = userdata;
932 r = bus_verify_polkit_async(
935 "org.freedesktop.login1.lock-sessions",
943 return 1; /* Will call us back */
945 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
949 return sd_bus_reply_method_return(message, NULL);
952 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
954 Manager *m = userdata;
962 r = sd_bus_message_read(message, "s", &name);
966 r = manager_get_session_from_creds(m, message, name, error, &session);
970 return bus_session_method_kill(bus, message, session, error);
973 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
974 Manager *m = userdata;
983 r = sd_bus_message_read(message, "u", &uid);
987 r = manager_get_user_from_creds(m, message, uid, error, &user);
991 return bus_user_method_kill(bus, message, user, error);
994 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
995 Manager *m = userdata;
1004 r = sd_bus_message_read(message, "s", &name);
1008 r = manager_get_session_from_creds(m, message, name, error, &session);
1012 return bus_session_method_terminate(bus, message, session, error);
1015 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1016 Manager *m = userdata;
1025 r = sd_bus_message_read(message, "u", &uid);
1029 r = manager_get_user_from_creds(m, message, uid, error, &user);
1033 return bus_user_method_terminate(bus, message, user, error);
1036 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1037 Manager *m = userdata;
1046 r = sd_bus_message_read(message, "s", &name);
1050 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1054 return bus_seat_method_terminate(bus, message, seat, error);
1057 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1058 _cleanup_free_ char *cc = NULL;
1059 Manager *m = userdata;
1070 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1074 if (uid == UID_INVALID) {
1075 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1077 /* Note that we get the owner UID of the session, not the actual client UID here! */
1078 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1082 r = sd_bus_creds_get_owner_uid(creds, &uid);
1090 return errno ? -errno : -ENOENT;
1092 r = bus_verify_polkit_async(
1095 "org.freedesktop.login1.set-user-linger",
1098 &m->polkit_registry,
1103 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1105 mkdir_p_label("/var/lib/systemd", 0755);
1107 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1111 cc = cescape(pw->pw_name);
1115 path = strjoina("/var/lib/systemd/linger/", cc);
1123 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1130 if (r < 0 && errno != ENOENT)
1133 u = hashmap_get(m->users, UID_TO_PTR(uid));
1135 user_add_to_gc_queue(u);
1138 return sd_bus_reply_method_return(message, NULL);
1141 static int trigger_device(Manager *m, struct udev_device *d) {
1142 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1143 struct udev_list_entry *first, *item;
1148 e = udev_enumerate_new(m->udev);
1153 r = udev_enumerate_add_match_parent(e, d);
1158 r = udev_enumerate_scan_devices(e);
1162 first = udev_enumerate_get_list_entry(e);
1163 udev_list_entry_foreach(item, first) {
1164 _cleanup_free_ char *t = NULL;
1167 p = udev_list_entry_get_name(item);
1169 t = strappend(p, "/uevent");
1173 write_string_file(t, "change");
1179 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1180 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1181 _cleanup_free_ char *rule = NULL, *file = NULL;
1182 const char *id_for_seat;
1189 d = udev_device_new_from_syspath(m->udev, sysfs);
1193 if (!udev_device_has_tag(d, "seat"))
1196 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1200 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1203 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1206 mkdir_p_label("/etc/udev/rules.d", 0755);
1207 mac_selinux_init("/etc");
1208 r = write_string_file_atomic_label(file, rule);
1212 return trigger_device(m, d);
1215 static int flush_devices(Manager *m) {
1216 _cleanup_closedir_ DIR *d;
1220 d = opendir("/etc/udev/rules.d");
1222 if (errno != ENOENT)
1223 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1227 while ((de = readdir(d))) {
1229 if (!dirent_is_file(de))
1232 if (!startswith(de->d_name, "72-seat-"))
1235 if (!endswith(de->d_name, ".rules"))
1238 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1239 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1243 return trigger_device(m, NULL);
1246 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1247 const char *sysfs, *seat;
1248 Manager *m = userdata;
1255 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1259 if (!path_startswith(sysfs, "/sys"))
1260 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1262 if (!seat_name_is_valid(seat))
1263 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1265 r = bus_verify_polkit_async(
1268 "org.freedesktop.login1.attach-device",
1271 &m->polkit_registry,
1276 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1278 r = attach_device(m, seat, sysfs);
1282 return sd_bus_reply_method_return(message, NULL);
1285 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1286 Manager *m = userdata;
1293 r = sd_bus_message_read(message, "b", &interactive);
1297 r = bus_verify_polkit_async(
1300 "org.freedesktop.login1.flush-devices",
1303 &m->polkit_registry,
1308 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1310 r = flush_devices(m);
1314 return sd_bus_reply_method_return(message, NULL);
1317 static int have_multiple_sessions(
1326 /* Check for other users' sessions. Greeter sessions do not
1327 * count, and non-login sessions do not count either. */
1328 HASHMAP_FOREACH(session, m->sessions, i)
1329 if (session->class == SESSION_USER &&
1330 session->user->uid != uid)
1336 static int bus_manager_log_shutdown(
1339 const char *unit_name) {
1346 if (w != INHIBIT_SHUTDOWN)
1349 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1350 p = "MESSAGE=System is powering down.";
1351 q = "SHUTDOWN=power-off";
1352 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1353 p = "MESSAGE=System is halting.";
1354 q = "SHUTDOWN=halt";
1355 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1356 p = "MESSAGE=System is rebooting.";
1357 q = "SHUTDOWN=reboot";
1358 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1359 p = "MESSAGE=System is rebooting with kexec.";
1360 q = "SHUTDOWN=kexec";
1362 p = "MESSAGE=System is shutting down.";
1366 return log_struct(LOG_NOTICE,
1367 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1373 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1374 Manager *m = userdata;
1379 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1383 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1388 if (until <= now(CLOCK_MONOTONIC))
1391 /* We want to ignore the lid switch for a while after each
1392 * suspend, and after boot-up. Hence let's install a timer for
1393 * this. As long as the event source exists we ignore the lid
1396 if (m->lid_switch_ignore_event_source) {
1399 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1406 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1408 r = sd_event_add_time(
1410 &m->lid_switch_ignore_event_source,
1413 lid_switch_ignore_handler, m);
1418 static int execute_shutdown_or_sleep(
1421 const char *unit_name,
1422 sd_bus_error *error) {
1424 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1431 assert(w < _INHIBIT_WHAT_MAX);
1434 bus_manager_log_shutdown(m, w, unit_name);
1436 r = sd_bus_call_method(
1438 "org.freedesktop.systemd1",
1439 "/org/freedesktop/systemd1",
1440 "org.freedesktop.systemd1.Manager",
1444 "ss", unit_name, "replace-irreversibly");
1448 r = sd_bus_message_read(reply, "o", &p);
1456 m->action_unit = unit_name;
1457 free(m->action_job);
1461 /* Make sure the lid switch is ignored for a while */
1462 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1467 static int delay_shutdown_or_sleep(
1470 const char *unit_name) {
1474 assert(w < _INHIBIT_WHAT_MAX);
1477 m->action_timestamp = now(CLOCK_MONOTONIC);
1478 m->action_unit = unit_name;
1484 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1486 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1487 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1488 [INHIBIT_SLEEP] = "PrepareForSleep"
1491 int active = _active;
1495 assert(w < _INHIBIT_WHAT_MAX);
1496 assert(signal_name[w]);
1498 return sd_bus_emit_signal(m->bus,
1499 "/org/freedesktop/login1",
1500 "org.freedesktop.login1.Manager",
1506 int bus_manager_shutdown_or_sleep_now_or_later(
1508 const char *unit_name,
1510 sd_bus_error *error) {
1518 assert(w <= _INHIBIT_WHAT_MAX);
1519 assert(!m->action_job);
1521 /* Tell everybody to prepare for shutdown/sleep */
1522 send_prepare_for(m, w, true);
1525 m->inhibit_delay_max > 0 &&
1526 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1529 /* Shutdown is delayed, keep in mind what we
1530 * want to do, and start a timeout */
1531 r = delay_shutdown_or_sleep(m, w, unit_name);
1533 /* Shutdown is not delayed, execute it
1535 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1540 static int method_do_shutdown_or_sleep(
1542 sd_bus_message *message,
1543 const char *unit_name,
1546 const char *action_multiple_sessions,
1547 const char *action_ignore_inhibit,
1548 const char *sleep_verb,
1549 sd_bus_message_handler_t method,
1550 sd_bus_error *error) {
1552 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1553 bool multiple_sessions, blocked;
1561 assert(w <= _INHIBIT_WHAT_MAX);
1563 assert(action_multiple_sessions);
1564 assert(action_ignore_inhibit);
1567 r = sd_bus_message_read(message, "b", &interactive);
1571 /* Don't allow multiple jobs being executed at the same time */
1573 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1576 r = can_sleep(sleep_verb);
1581 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1584 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1588 r = sd_bus_creds_get_euid(creds, &uid);
1592 r = have_multiple_sessions(m, uid);
1596 multiple_sessions = r > 0;
1597 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1599 if (multiple_sessions) {
1600 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1604 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1608 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1612 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1615 if (!multiple_sessions && !blocked) {
1616 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1620 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1623 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1627 return sd_bus_reply_method_return(message, NULL);
1630 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1631 Manager *m = userdata;
1633 return method_do_shutdown_or_sleep(
1635 SPECIAL_POWEROFF_TARGET,
1637 "org.freedesktop.login1.power-off",
1638 "org.freedesktop.login1.power-off-multiple-sessions",
1639 "org.freedesktop.login1.power-off-ignore-inhibit",
1645 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1646 Manager *m = userdata;
1648 return method_do_shutdown_or_sleep(
1650 SPECIAL_REBOOT_TARGET,
1652 "org.freedesktop.login1.reboot",
1653 "org.freedesktop.login1.reboot-multiple-sessions",
1654 "org.freedesktop.login1.reboot-ignore-inhibit",
1660 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1661 Manager *m = userdata;
1663 return method_do_shutdown_or_sleep(
1665 SPECIAL_SUSPEND_TARGET,
1667 "org.freedesktop.login1.suspend",
1668 "org.freedesktop.login1.suspend-multiple-sessions",
1669 "org.freedesktop.login1.suspend-ignore-inhibit",
1675 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1676 Manager *m = userdata;
1678 return method_do_shutdown_or_sleep(
1680 SPECIAL_HIBERNATE_TARGET,
1682 "org.freedesktop.login1.hibernate",
1683 "org.freedesktop.login1.hibernate-multiple-sessions",
1684 "org.freedesktop.login1.hibernate-ignore-inhibit",
1690 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1691 Manager *m = userdata;
1693 return method_do_shutdown_or_sleep(
1695 SPECIAL_HYBRID_SLEEP_TARGET,
1697 "org.freedesktop.login1.hibernate",
1698 "org.freedesktop.login1.hibernate-multiple-sessions",
1699 "org.freedesktop.login1.hibernate-ignore-inhibit",
1701 method_hybrid_sleep,
1705 static int method_can_shutdown_or_sleep(
1707 sd_bus_message *message,
1710 const char *action_multiple_sessions,
1711 const char *action_ignore_inhibit,
1712 const char *sleep_verb,
1713 sd_bus_error *error) {
1715 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1716 bool multiple_sessions, challenge, blocked;
1717 const char *result = NULL;
1724 assert(w <= _INHIBIT_WHAT_MAX);
1726 assert(action_multiple_sessions);
1727 assert(action_ignore_inhibit);
1730 r = can_sleep(sleep_verb);
1734 return sd_bus_reply_method_return(message, "s", "na");
1737 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1741 r = sd_bus_creds_get_euid(creds, &uid);
1745 r = have_multiple_sessions(m, uid);
1749 multiple_sessions = r > 0;
1750 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1752 if (multiple_sessions) {
1753 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, UID_INVALID, &challenge, error);
1760 result = "challenge";
1766 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, UID_INVALID, &challenge, error);
1770 if (r > 0 && !result)
1772 else if (challenge && (!result || streq(result, "yes")))
1773 result = "challenge";
1778 if (!multiple_sessions && !blocked) {
1779 /* If neither inhibit nor multiple sessions
1780 * apply then just check the normal policy */
1782 r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, UID_INVALID, &challenge, error);
1789 result = "challenge";
1794 return sd_bus_reply_method_return(message, "s", result);
1797 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1798 Manager *m = userdata;
1800 return method_can_shutdown_or_sleep(
1803 "org.freedesktop.login1.power-off",
1804 "org.freedesktop.login1.power-off-multiple-sessions",
1805 "org.freedesktop.login1.power-off-ignore-inhibit",
1810 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1811 Manager *m = userdata;
1813 return method_can_shutdown_or_sleep(
1816 "org.freedesktop.login1.reboot",
1817 "org.freedesktop.login1.reboot-multiple-sessions",
1818 "org.freedesktop.login1.reboot-ignore-inhibit",
1823 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1824 Manager *m = userdata;
1826 return method_can_shutdown_or_sleep(
1829 "org.freedesktop.login1.suspend",
1830 "org.freedesktop.login1.suspend-multiple-sessions",
1831 "org.freedesktop.login1.suspend-ignore-inhibit",
1836 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1837 Manager *m = userdata;
1839 return method_can_shutdown_or_sleep(
1842 "org.freedesktop.login1.hibernate",
1843 "org.freedesktop.login1.hibernate-multiple-sessions",
1844 "org.freedesktop.login1.hibernate-ignore-inhibit",
1849 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1850 Manager *m = userdata;
1852 return method_can_shutdown_or_sleep(
1855 "org.freedesktop.login1.hibernate",
1856 "org.freedesktop.login1.hibernate-multiple-sessions",
1857 "org.freedesktop.login1.hibernate-ignore-inhibit",
1862 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1863 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1864 const char *who, *why, *what, *mode;
1865 _cleanup_free_ char *id = NULL;
1866 _cleanup_close_ int fifo_fd = -1;
1867 Manager *m = userdata;
1868 Inhibitor *i = NULL;
1879 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1883 w = inhibit_what_from_string(what);
1885 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1887 mm = inhibit_mode_from_string(mode);
1889 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1891 /* Delay is only supported for shutdown/sleep */
1892 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1893 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1895 /* Don't allow taking delay locks while we are already
1896 * executing the operation. We shouldn't create the impression
1897 * that the lock was successful if the machine is about to go
1898 * down/suspend any moment. */
1899 if (m->action_what & w)
1900 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1902 r = bus_verify_polkit_async(
1905 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1906 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1907 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1908 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1909 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1910 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1911 "org.freedesktop.login1.inhibit-handle-lid-switch",
1914 &m->polkit_registry,
1919 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1921 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
1925 r = sd_bus_creds_get_euid(creds, &uid);
1929 r = sd_bus_creds_get_pid(creds, &pid);
1937 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1940 } while (hashmap_get(m->inhibitors, id));
1942 r = manager_add_inhibitor(m, id, &i);
1950 i->why = strdup(why);
1951 i->who = strdup(who);
1953 if (!i->why || !i->who) {
1958 fifo_fd = inhibitor_create_fifo(i);
1966 return sd_bus_reply_method_return(message, "h", fifo_fd);
1975 const sd_bus_vtable manager_vtable[] = {
1976 SD_BUS_VTABLE_START(0),
1978 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
1979 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
1980 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
1981 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
1982 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1983 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1984 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1985 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1986 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1987 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
1988 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
1989 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
1990 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
1991 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
1992 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
1993 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1994 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
1995 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1996 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1997 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1999 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2000 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2001 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2002 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2003 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2006 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2007 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2008 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2009 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2010 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2011 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2012 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2013 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2014 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2015 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2016 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2017 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2018 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2019 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2020 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2021 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2022 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2023 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2024 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2026 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2027 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2028 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2029 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2030 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2031 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2032 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2033 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2034 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2036 SD_BUS_SIGNAL("SessionNew", "so", 0),
2037 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2038 SD_BUS_SIGNAL("UserNew", "uo", 0),
2039 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2040 SD_BUS_SIGNAL("SeatNew", "so", 0),
2041 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2042 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2043 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2048 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2057 if (streq(result, "done"))
2058 r = session_send_create_reply(s, NULL);
2060 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2062 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2063 r = session_send_create_reply(s, &e);
2069 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2070 const char *path, *result, *unit;
2071 Manager *m = userdata;
2081 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2083 bus_log_parse_error(r);
2087 if (m->action_job && streq(m->action_job, path)) {
2088 log_info("Operation finished.");
2090 /* Tell people that they now may take a lock again */
2091 send_prepare_for(m, m->action_what, false);
2093 free(m->action_job);
2094 m->action_job = NULL;
2095 m->action_unit = NULL;
2100 session = hashmap_get(m->session_units, unit);
2103 if (streq_ptr(path, session->scope_job)) {
2104 free(session->scope_job);
2105 session->scope_job = NULL;
2108 session_jobs_reply(session, unit, result);
2110 session_save(session);
2111 session_add_to_gc_queue(session);
2114 user = hashmap_get(m->user_units, unit);
2117 if (streq_ptr(path, user->service_job)) {
2118 free(user->service_job);
2119 user->service_job = NULL;
2122 if (streq_ptr(path, user->slice_job)) {
2123 free(user->slice_job);
2124 user->slice_job = NULL;
2127 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2128 session_jobs_reply(session, unit, result);
2132 user_add_to_gc_queue(user);
2138 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2139 const char *path, *unit;
2140 Manager *m = userdata;
2149 r = sd_bus_message_read(message, "so", &unit, &path);
2151 bus_log_parse_error(r);
2155 session = hashmap_get(m->session_units, unit);
2157 session_add_to_gc_queue(session);
2159 user = hashmap_get(m->user_units, unit);
2161 user_add_to_gc_queue(user);
2166 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2167 _cleanup_free_ char *unit = NULL;
2168 Manager *m = userdata;
2178 path = sd_bus_message_get_path(message);
2182 r = unit_name_from_dbus_path(path, &unit);
2183 if (r == -EINVAL) /* not a unit */
2188 session = hashmap_get(m->session_units, unit);
2190 session_add_to_gc_queue(session);
2192 user = hashmap_get(m->user_units, unit);
2194 user_add_to_gc_queue(user);
2199 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2200 Manager *m = userdata;
2207 r = sd_bus_message_read(message, "b", &b);
2209 bus_log_parse_error(r);
2216 /* systemd finished reloading, let's recheck all our sessions */
2217 log_debug("System manager has been reloaded, rechecking sessions...");
2219 HASHMAP_FOREACH(session, m->sessions, i)
2220 session_add_to_gc_queue(session);
2225 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2226 const char *name, *old, *new;
2227 Manager *m = userdata;
2235 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2237 bus_log_parse_error(r);
2241 if (isempty(old) || !isempty(new))
2244 key = set_remove(m->busnames, (char*) old);
2248 /* Drop all controllers owned by this name */
2252 HASHMAP_FOREACH(session, m->sessions, i)
2253 if (session_is_controller(session, old))
2254 session_drop_controller(session);
2259 int manager_send_changed(Manager *manager, const char *property, ...) {
2264 l = strv_from_stdarg_alloca(property);
2266 return sd_bus_emit_properties_changed_strv(
2268 "/org/freedesktop/login1",
2269 "org.freedesktop.login1.Manager",
2273 int manager_dispatch_delayed(Manager *manager) {
2274 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2275 Inhibitor *offending = NULL;
2280 if (manager->action_what == 0 || manager->action_job)
2283 /* Continue delay? */
2284 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
2285 _cleanup_free_ char *comm = NULL, *u = NULL;
2287 get_process_comm(offending->pid, &comm);
2288 u = uid_to_name(offending->uid);
2290 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2293 log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
2294 offending->uid, strna(u),
2295 offending->pid, strna(comm));
2298 /* Actually do the operation */
2299 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
2301 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2303 manager->action_unit = NULL;
2304 manager->action_what = 0;
2311 int manager_start_scope(
2316 const char *description,
2317 const char *after, const char *after2,
2318 sd_bus_error *error,
2321 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2328 r = sd_bus_message_new_method_call(
2331 "org.freedesktop.systemd1",
2332 "/org/freedesktop/systemd1",
2333 "org.freedesktop.systemd1.Manager",
2334 "StartTransientUnit");
2338 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2342 r = sd_bus_message_open_container(m, 'a', "(sv)");
2346 if (!isempty(slice)) {
2347 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2352 if (!isempty(description)) {
2353 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2358 if (!isempty(after)) {
2359 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2364 if (!isempty(after2)) {
2365 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2370 /* cgroup empty notification is not available in containers
2371 * currently. To make this less problematic, let's shorten the
2372 * stop timeout for sessions, so that we don't wait
2375 /* Make sure that the session shells are terminated with
2376 * SIGHUP since bash and friends tend to ignore SIGTERM */
2377 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2381 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2385 r = sd_bus_message_close_container(m);
2389 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2393 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2401 r = sd_bus_message_read(reply, "o", &j);
2415 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2416 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2422 r = sd_bus_call_method(
2424 "org.freedesktop.systemd1",
2425 "/org/freedesktop/systemd1",
2426 "org.freedesktop.systemd1.Manager",
2430 "ss", unit, "fail");
2438 r = sd_bus_message_read(reply, "o", &j);
2452 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2453 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2459 r = sd_bus_call_method(
2461 "org.freedesktop.systemd1",
2462 "/org/freedesktop/systemd1",
2463 "org.freedesktop.systemd1.Manager",
2467 "ss", unit, "fail");
2469 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2470 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2475 sd_bus_error_free(error);
2486 r = sd_bus_message_read(reply, "o", &j);
2500 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2501 _cleanup_free_ char *path = NULL;
2507 path = unit_dbus_path_from_name(scope);
2511 r = sd_bus_call_method(
2513 "org.freedesktop.systemd1",
2515 "org.freedesktop.systemd1.Scope",
2521 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2522 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2523 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2524 sd_bus_error_free(error);
2534 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2538 return sd_bus_call_method(
2540 "org.freedesktop.systemd1",
2541 "/org/freedesktop/systemd1",
2542 "org.freedesktop.systemd1.Manager",
2546 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2549 int manager_unit_is_active(Manager *manager, const char *unit) {
2550 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2551 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2552 _cleanup_free_ char *path = NULL;
2559 path = unit_dbus_path_from_name(unit);
2563 r = sd_bus_get_property(
2565 "org.freedesktop.systemd1",
2567 "org.freedesktop.systemd1.Unit",
2573 /* systemd might have droppped off momentarily, let's
2574 * not make this an error */
2575 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2576 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2579 /* If the unit is already unloaded then it's not
2581 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2582 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2588 r = sd_bus_message_read(reply, "s", &state);
2592 return !streq(state, "inactive") && !streq(state, "failed");
2595 int manager_job_is_active(Manager *manager, const char *path) {
2596 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2597 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2603 r = sd_bus_get_property(
2605 "org.freedesktop.systemd1",
2607 "org.freedesktop.systemd1.Job",
2613 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2614 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2617 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2623 /* We don't actually care about the state really. The fact
2624 * that we could read the job state is enough for us */