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(). */
804 session_add_to_gc_queue(session);
807 user_add_to_gc_queue(user);
812 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
813 Manager *m = userdata;
822 r = sd_bus_message_read(message, "s", &name);
826 r = manager_get_session_from_creds(m, message, name, error, &session);
830 r = session_release(session);
834 return sd_bus_reply_method_return(message, NULL);
837 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
838 Manager *m = userdata;
847 r = sd_bus_message_read(message, "s", &name);
851 r = manager_get_session_from_creds(m, message, name, error, &session);
855 return bus_session_method_activate(bus, message, session, error);
858 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
859 const char *session_name, *seat_name;
860 Manager *m = userdata;
869 /* Same as ActivateSession() but refuses to work if
870 * the seat doesn't match */
872 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
876 r = manager_get_session_from_creds(m, message, session_name, error, &session);
880 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
884 if (session->seat != seat)
885 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
887 r = session_activate(session);
891 return sd_bus_reply_method_return(message, NULL);
894 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
895 Manager *m = userdata;
904 r = sd_bus_message_read(message, "s", &name);
908 r = manager_get_session_from_creds(m, message, name, error, &session);
912 return bus_session_method_lock(bus, message, session, error);
915 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
916 Manager *m = userdata;
923 r = bus_verify_polkit_async(
926 "org.freedesktop.login1.lock-sessions",
934 return 1; /* Will call us back */
936 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
940 return sd_bus_reply_method_return(message, NULL);
943 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
945 Manager *m = userdata;
953 r = sd_bus_message_read(message, "s", &name);
957 r = manager_get_session_from_creds(m, message, name, error, &session);
961 return bus_session_method_kill(bus, message, session, error);
964 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
965 Manager *m = userdata;
974 r = sd_bus_message_read(message, "u", &uid);
978 r = manager_get_user_from_creds(m, message, uid, error, &user);
982 return bus_user_method_kill(bus, message, user, error);
985 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
986 Manager *m = userdata;
995 r = sd_bus_message_read(message, "s", &name);
999 r = manager_get_session_from_creds(m, message, name, error, &session);
1003 return bus_session_method_terminate(bus, message, session, error);
1006 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1007 Manager *m = userdata;
1016 r = sd_bus_message_read(message, "u", &uid);
1020 r = manager_get_user_from_creds(m, message, uid, error, &user);
1024 return bus_user_method_terminate(bus, message, user, error);
1027 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1028 Manager *m = userdata;
1037 r = sd_bus_message_read(message, "s", &name);
1041 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1045 return bus_seat_method_terminate(bus, message, seat, error);
1048 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1049 _cleanup_free_ char *cc = NULL;
1050 Manager *m = userdata;
1061 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1065 if (uid == UID_INVALID) {
1066 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1068 /* Note that we get the owner UID of the session, not the actual client UID here! */
1069 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1073 r = sd_bus_creds_get_owner_uid(creds, &uid);
1081 return errno ? -errno : -ENOENT;
1083 r = bus_verify_polkit_async(
1086 "org.freedesktop.login1.set-user-linger",
1089 &m->polkit_registry,
1094 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1096 mkdir_p_label("/var/lib/systemd", 0755);
1098 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1102 cc = cescape(pw->pw_name);
1106 path = strjoina("/var/lib/systemd/linger/", cc);
1114 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1121 if (r < 0 && errno != ENOENT)
1124 u = hashmap_get(m->users, UID_TO_PTR(uid));
1126 user_add_to_gc_queue(u);
1129 return sd_bus_reply_method_return(message, NULL);
1132 static int trigger_device(Manager *m, struct udev_device *d) {
1133 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1134 struct udev_list_entry *first, *item;
1139 e = udev_enumerate_new(m->udev);
1144 r = udev_enumerate_add_match_parent(e, d);
1149 r = udev_enumerate_scan_devices(e);
1153 first = udev_enumerate_get_list_entry(e);
1154 udev_list_entry_foreach(item, first) {
1155 _cleanup_free_ char *t = NULL;
1158 p = udev_list_entry_get_name(item);
1160 t = strappend(p, "/uevent");
1164 write_string_file(t, "change");
1170 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1171 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1172 _cleanup_free_ char *rule = NULL, *file = NULL;
1173 const char *id_for_seat;
1180 d = udev_device_new_from_syspath(m->udev, sysfs);
1184 if (!udev_device_has_tag(d, "seat"))
1187 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1191 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1194 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1197 mkdir_p_label("/etc/udev/rules.d", 0755);
1198 mac_selinux_init("/etc");
1199 r = write_string_file_atomic_label(file, rule);
1203 return trigger_device(m, d);
1206 static int flush_devices(Manager *m) {
1207 _cleanup_closedir_ DIR *d;
1211 d = opendir("/etc/udev/rules.d");
1213 if (errno != ENOENT)
1214 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1218 while ((de = readdir(d))) {
1220 if (!dirent_is_file(de))
1223 if (!startswith(de->d_name, "72-seat-"))
1226 if (!endswith(de->d_name, ".rules"))
1229 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1230 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1234 return trigger_device(m, NULL);
1237 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1238 const char *sysfs, *seat;
1239 Manager *m = userdata;
1246 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1250 if (!path_startswith(sysfs, "/sys"))
1251 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1253 if (!seat_name_is_valid(seat))
1254 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1256 r = bus_verify_polkit_async(
1259 "org.freedesktop.login1.attach-device",
1262 &m->polkit_registry,
1267 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1269 r = attach_device(m, seat, sysfs);
1273 return sd_bus_reply_method_return(message, NULL);
1276 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1277 Manager *m = userdata;
1284 r = sd_bus_message_read(message, "b", &interactive);
1288 r = bus_verify_polkit_async(
1291 "org.freedesktop.login1.flush-devices",
1294 &m->polkit_registry,
1299 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1301 r = flush_devices(m);
1305 return sd_bus_reply_method_return(message, NULL);
1308 static int have_multiple_sessions(
1317 /* Check for other users' sessions. Greeter sessions do not
1318 * count, and non-login sessions do not count either. */
1319 HASHMAP_FOREACH(session, m->sessions, i)
1320 if (session->class == SESSION_USER &&
1321 session->user->uid != uid)
1327 static int bus_manager_log_shutdown(
1330 const char *unit_name) {
1337 if (w != INHIBIT_SHUTDOWN)
1340 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1341 p = "MESSAGE=System is powering down.";
1342 q = "SHUTDOWN=power-off";
1343 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1344 p = "MESSAGE=System is halting.";
1345 q = "SHUTDOWN=halt";
1346 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1347 p = "MESSAGE=System is rebooting.";
1348 q = "SHUTDOWN=reboot";
1349 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1350 p = "MESSAGE=System is rebooting with kexec.";
1351 q = "SHUTDOWN=kexec";
1353 p = "MESSAGE=System is shutting down.";
1357 return log_struct(LOG_NOTICE,
1358 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1364 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1365 Manager *m = userdata;
1370 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1374 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1379 if (until <= now(CLOCK_MONOTONIC))
1382 /* We want to ignore the lid switch for a while after each
1383 * suspend, and after boot-up. Hence let's install a timer for
1384 * this. As long as the event source exists we ignore the lid
1387 if (m->lid_switch_ignore_event_source) {
1390 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1397 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1399 r = sd_event_add_time(
1401 &m->lid_switch_ignore_event_source,
1404 lid_switch_ignore_handler, m);
1409 static int execute_shutdown_or_sleep(
1412 const char *unit_name,
1413 sd_bus_error *error) {
1415 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1422 assert(w < _INHIBIT_WHAT_MAX);
1425 bus_manager_log_shutdown(m, w, unit_name);
1427 r = sd_bus_call_method(
1429 "org.freedesktop.systemd1",
1430 "/org/freedesktop/systemd1",
1431 "org.freedesktop.systemd1.Manager",
1435 "ss", unit_name, "replace-irreversibly");
1439 r = sd_bus_message_read(reply, "o", &p);
1447 m->action_unit = unit_name;
1448 free(m->action_job);
1452 /* Make sure the lid switch is ignored for a while */
1453 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1458 static int delay_shutdown_or_sleep(
1461 const char *unit_name) {
1465 assert(w < _INHIBIT_WHAT_MAX);
1468 m->action_timestamp = now(CLOCK_MONOTONIC);
1469 m->action_unit = unit_name;
1475 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1477 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1478 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1479 [INHIBIT_SLEEP] = "PrepareForSleep"
1482 int active = _active;
1486 assert(w < _INHIBIT_WHAT_MAX);
1487 assert(signal_name[w]);
1489 return sd_bus_emit_signal(m->bus,
1490 "/org/freedesktop/login1",
1491 "org.freedesktop.login1.Manager",
1497 int bus_manager_shutdown_or_sleep_now_or_later(
1499 const char *unit_name,
1501 sd_bus_error *error) {
1509 assert(w <= _INHIBIT_WHAT_MAX);
1510 assert(!m->action_job);
1512 /* Tell everybody to prepare for shutdown/sleep */
1513 send_prepare_for(m, w, true);
1516 m->inhibit_delay_max > 0 &&
1517 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1520 /* Shutdown is delayed, keep in mind what we
1521 * want to do, and start a timeout */
1522 r = delay_shutdown_or_sleep(m, w, unit_name);
1524 /* Shutdown is not delayed, execute it
1526 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1531 static int method_do_shutdown_or_sleep(
1533 sd_bus_message *message,
1534 const char *unit_name,
1537 const char *action_multiple_sessions,
1538 const char *action_ignore_inhibit,
1539 const char *sleep_verb,
1540 sd_bus_message_handler_t method,
1541 sd_bus_error *error) {
1543 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1544 bool multiple_sessions, blocked;
1552 assert(w <= _INHIBIT_WHAT_MAX);
1554 assert(action_multiple_sessions);
1555 assert(action_ignore_inhibit);
1558 r = sd_bus_message_read(message, "b", &interactive);
1562 /* Don't allow multiple jobs being executed at the same time */
1564 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1567 r = can_sleep(sleep_verb);
1572 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1575 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1579 r = sd_bus_creds_get_euid(creds, &uid);
1583 r = have_multiple_sessions(m, uid);
1587 multiple_sessions = r > 0;
1588 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1590 if (multiple_sessions) {
1591 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1595 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1599 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1603 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1606 if (!multiple_sessions && !blocked) {
1607 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1611 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1614 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1618 return sd_bus_reply_method_return(message, NULL);
1621 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1622 Manager *m = userdata;
1624 return method_do_shutdown_or_sleep(
1626 SPECIAL_POWEROFF_TARGET,
1628 "org.freedesktop.login1.power-off",
1629 "org.freedesktop.login1.power-off-multiple-sessions",
1630 "org.freedesktop.login1.power-off-ignore-inhibit",
1636 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1637 Manager *m = userdata;
1639 return method_do_shutdown_or_sleep(
1641 SPECIAL_REBOOT_TARGET,
1643 "org.freedesktop.login1.reboot",
1644 "org.freedesktop.login1.reboot-multiple-sessions",
1645 "org.freedesktop.login1.reboot-ignore-inhibit",
1651 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1652 Manager *m = userdata;
1654 return method_do_shutdown_or_sleep(
1656 SPECIAL_SUSPEND_TARGET,
1658 "org.freedesktop.login1.suspend",
1659 "org.freedesktop.login1.suspend-multiple-sessions",
1660 "org.freedesktop.login1.suspend-ignore-inhibit",
1666 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1667 Manager *m = userdata;
1669 return method_do_shutdown_or_sleep(
1671 SPECIAL_HIBERNATE_TARGET,
1673 "org.freedesktop.login1.hibernate",
1674 "org.freedesktop.login1.hibernate-multiple-sessions",
1675 "org.freedesktop.login1.hibernate-ignore-inhibit",
1681 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1682 Manager *m = userdata;
1684 return method_do_shutdown_or_sleep(
1686 SPECIAL_HYBRID_SLEEP_TARGET,
1688 "org.freedesktop.login1.hibernate",
1689 "org.freedesktop.login1.hibernate-multiple-sessions",
1690 "org.freedesktop.login1.hibernate-ignore-inhibit",
1692 method_hybrid_sleep,
1696 static int method_can_shutdown_or_sleep(
1698 sd_bus_message *message,
1701 const char *action_multiple_sessions,
1702 const char *action_ignore_inhibit,
1703 const char *sleep_verb,
1704 sd_bus_error *error) {
1706 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1707 bool multiple_sessions, challenge, blocked;
1708 const char *result = NULL;
1715 assert(w <= _INHIBIT_WHAT_MAX);
1717 assert(action_multiple_sessions);
1718 assert(action_ignore_inhibit);
1721 r = can_sleep(sleep_verb);
1725 return sd_bus_reply_method_return(message, "s", "na");
1728 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1732 r = sd_bus_creds_get_euid(creds, &uid);
1736 r = have_multiple_sessions(m, uid);
1740 multiple_sessions = r > 0;
1741 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1743 if (multiple_sessions) {
1744 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, UID_INVALID, &challenge, error);
1751 result = "challenge";
1757 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, UID_INVALID, &challenge, error);
1761 if (r > 0 && !result)
1763 else if (challenge && (!result || streq(result, "yes")))
1764 result = "challenge";
1769 if (!multiple_sessions && !blocked) {
1770 /* If neither inhibit nor multiple sessions
1771 * apply then just check the normal policy */
1773 r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, UID_INVALID, &challenge, error);
1780 result = "challenge";
1785 return sd_bus_reply_method_return(message, "s", result);
1788 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1789 Manager *m = userdata;
1791 return method_can_shutdown_or_sleep(
1794 "org.freedesktop.login1.power-off",
1795 "org.freedesktop.login1.power-off-multiple-sessions",
1796 "org.freedesktop.login1.power-off-ignore-inhibit",
1801 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1802 Manager *m = userdata;
1804 return method_can_shutdown_or_sleep(
1807 "org.freedesktop.login1.reboot",
1808 "org.freedesktop.login1.reboot-multiple-sessions",
1809 "org.freedesktop.login1.reboot-ignore-inhibit",
1814 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1815 Manager *m = userdata;
1817 return method_can_shutdown_or_sleep(
1820 "org.freedesktop.login1.suspend",
1821 "org.freedesktop.login1.suspend-multiple-sessions",
1822 "org.freedesktop.login1.suspend-ignore-inhibit",
1827 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1828 Manager *m = userdata;
1830 return method_can_shutdown_or_sleep(
1833 "org.freedesktop.login1.hibernate",
1834 "org.freedesktop.login1.hibernate-multiple-sessions",
1835 "org.freedesktop.login1.hibernate-ignore-inhibit",
1840 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1841 Manager *m = userdata;
1843 return method_can_shutdown_or_sleep(
1846 "org.freedesktop.login1.hibernate",
1847 "org.freedesktop.login1.hibernate-multiple-sessions",
1848 "org.freedesktop.login1.hibernate-ignore-inhibit",
1853 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1854 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1855 const char *who, *why, *what, *mode;
1856 _cleanup_free_ char *id = NULL;
1857 _cleanup_close_ int fifo_fd = -1;
1858 Manager *m = userdata;
1859 Inhibitor *i = NULL;
1870 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1874 w = inhibit_what_from_string(what);
1876 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1878 mm = inhibit_mode_from_string(mode);
1880 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1882 /* Delay is only supported for shutdown/sleep */
1883 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1884 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1886 /* Don't allow taking delay locks while we are already
1887 * executing the operation. We shouldn't create the impression
1888 * that the lock was successful if the machine is about to go
1889 * down/suspend any moment. */
1890 if (m->action_what & w)
1891 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1893 r = bus_verify_polkit_async(
1896 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1897 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1898 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1899 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1900 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1901 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1902 "org.freedesktop.login1.inhibit-handle-lid-switch",
1905 &m->polkit_registry,
1910 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1912 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
1916 r = sd_bus_creds_get_euid(creds, &uid);
1920 r = sd_bus_creds_get_pid(creds, &pid);
1928 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1931 } while (hashmap_get(m->inhibitors, id));
1933 r = manager_add_inhibitor(m, id, &i);
1941 i->why = strdup(why);
1942 i->who = strdup(who);
1944 if (!i->why || !i->who) {
1949 fifo_fd = inhibitor_create_fifo(i);
1957 return sd_bus_reply_method_return(message, "h", fifo_fd);
1966 const sd_bus_vtable manager_vtable[] = {
1967 SD_BUS_VTABLE_START(0),
1969 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
1970 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
1971 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
1972 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
1973 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1974 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1975 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1976 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1977 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1978 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
1979 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
1980 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
1981 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
1982 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
1983 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
1984 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1985 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
1986 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1987 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1988 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1990 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
1991 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1992 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
1993 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1994 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1995 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
1996 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
1997 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
1998 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
1999 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2000 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2001 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2002 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2003 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2006 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2007 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2008 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2009 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2010 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2011 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2012 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2013 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2014 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2015 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2016 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2017 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2018 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2019 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2020 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2021 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2022 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2023 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2024 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2027 SD_BUS_SIGNAL("SessionNew", "so", 0),
2028 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2029 SD_BUS_SIGNAL("UserNew", "uo", 0),
2030 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2031 SD_BUS_SIGNAL("SeatNew", "so", 0),
2032 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2033 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2034 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2039 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2048 if (streq(result, "done"))
2049 r = session_send_create_reply(s, NULL);
2051 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2053 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2054 r = session_send_create_reply(s, &e);
2060 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2061 const char *path, *result, *unit;
2062 Manager *m = userdata;
2072 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2074 bus_log_parse_error(r);
2078 if (m->action_job && streq(m->action_job, path)) {
2079 log_info("Operation finished.");
2081 /* Tell people that they now may take a lock again */
2082 send_prepare_for(m, m->action_what, false);
2084 free(m->action_job);
2085 m->action_job = NULL;
2086 m->action_unit = NULL;
2091 session = hashmap_get(m->session_units, unit);
2094 if (streq_ptr(path, session->scope_job)) {
2095 free(session->scope_job);
2096 session->scope_job = NULL;
2099 session_jobs_reply(session, unit, result);
2101 session_save(session);
2102 session_add_to_gc_queue(session);
2105 user = hashmap_get(m->user_units, unit);
2108 if (streq_ptr(path, user->service_job)) {
2109 free(user->service_job);
2110 user->service_job = NULL;
2113 if (streq_ptr(path, user->slice_job)) {
2114 free(user->slice_job);
2115 user->slice_job = NULL;
2118 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2119 session_jobs_reply(session, unit, result);
2123 user_add_to_gc_queue(user);
2129 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2130 const char *path, *unit;
2131 Manager *m = userdata;
2140 r = sd_bus_message_read(message, "so", &unit, &path);
2142 bus_log_parse_error(r);
2146 session = hashmap_get(m->session_units, unit);
2148 session_add_to_gc_queue(session);
2150 user = hashmap_get(m->user_units, unit);
2152 user_add_to_gc_queue(user);
2157 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2158 _cleanup_free_ char *unit = NULL;
2159 Manager *m = userdata;
2169 path = sd_bus_message_get_path(message);
2173 r = unit_name_from_dbus_path(path, &unit);
2174 if (r == -EINVAL) /* not a unit */
2179 session = hashmap_get(m->session_units, unit);
2181 session_add_to_gc_queue(session);
2183 user = hashmap_get(m->user_units, unit);
2185 user_add_to_gc_queue(user);
2190 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2191 Manager *m = userdata;
2198 r = sd_bus_message_read(message, "b", &b);
2200 bus_log_parse_error(r);
2207 /* systemd finished reloading, let's recheck all our sessions */
2208 log_debug("System manager has been reloaded, rechecking sessions...");
2210 HASHMAP_FOREACH(session, m->sessions, i)
2211 session_add_to_gc_queue(session);
2216 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2217 const char *name, *old, *new;
2218 Manager *m = userdata;
2226 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2228 bus_log_parse_error(r);
2232 if (isempty(old) || !isempty(new))
2235 key = set_remove(m->busnames, (char*) old);
2239 /* Drop all controllers owned by this name */
2243 HASHMAP_FOREACH(session, m->sessions, i)
2244 if (session_is_controller(session, old))
2245 session_drop_controller(session);
2250 int manager_send_changed(Manager *manager, const char *property, ...) {
2255 l = strv_from_stdarg_alloca(property);
2257 return sd_bus_emit_properties_changed_strv(
2259 "/org/freedesktop/login1",
2260 "org.freedesktop.login1.Manager",
2264 int manager_dispatch_delayed(Manager *manager) {
2265 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2266 Inhibitor *offending = NULL;
2271 if (manager->action_what == 0 || manager->action_job)
2274 /* Continue delay? */
2275 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
2276 _cleanup_free_ char *comm = NULL, *u = NULL;
2278 get_process_comm(offending->pid, &comm);
2279 u = uid_to_name(offending->uid);
2281 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2284 log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
2285 offending->uid, strna(u),
2286 offending->pid, strna(comm));
2289 /* Actually do the operation */
2290 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
2292 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2294 manager->action_unit = NULL;
2295 manager->action_what = 0;
2302 int manager_start_scope(
2307 const char *description,
2308 const char *after, const char *after2,
2309 sd_bus_error *error,
2312 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2319 r = sd_bus_message_new_method_call(
2322 "org.freedesktop.systemd1",
2323 "/org/freedesktop/systemd1",
2324 "org.freedesktop.systemd1.Manager",
2325 "StartTransientUnit");
2329 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2333 r = sd_bus_message_open_container(m, 'a', "(sv)");
2337 if (!isempty(slice)) {
2338 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2343 if (!isempty(description)) {
2344 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2349 if (!isempty(after)) {
2350 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2355 if (!isempty(after2)) {
2356 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2361 /* cgroup empty notification is not available in containers
2362 * currently. To make this less problematic, let's shorten the
2363 * stop timeout for sessions, so that we don't wait
2366 /* Make sure that the session shells are terminated with
2367 * SIGHUP since bash and friends tend to ignore SIGTERM */
2368 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2372 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2376 r = sd_bus_message_close_container(m);
2380 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2384 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2392 r = sd_bus_message_read(reply, "o", &j);
2406 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2407 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2413 r = sd_bus_call_method(
2415 "org.freedesktop.systemd1",
2416 "/org/freedesktop/systemd1",
2417 "org.freedesktop.systemd1.Manager",
2421 "ss", unit, "fail");
2429 r = sd_bus_message_read(reply, "o", &j);
2443 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2444 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2450 r = sd_bus_call_method(
2452 "org.freedesktop.systemd1",
2453 "/org/freedesktop/systemd1",
2454 "org.freedesktop.systemd1.Manager",
2458 "ss", unit, "fail");
2460 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2461 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2466 sd_bus_error_free(error);
2477 r = sd_bus_message_read(reply, "o", &j);
2491 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2492 _cleanup_free_ char *path = NULL;
2498 path = unit_dbus_path_from_name(scope);
2502 r = sd_bus_call_method(
2504 "org.freedesktop.systemd1",
2506 "org.freedesktop.systemd1.Scope",
2512 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2513 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2514 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2515 sd_bus_error_free(error);
2525 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2529 return sd_bus_call_method(
2531 "org.freedesktop.systemd1",
2532 "/org/freedesktop/systemd1",
2533 "org.freedesktop.systemd1.Manager",
2537 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2540 int manager_unit_is_active(Manager *manager, const char *unit) {
2541 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2542 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2543 _cleanup_free_ char *path = NULL;
2550 path = unit_dbus_path_from_name(unit);
2554 r = sd_bus_get_property(
2556 "org.freedesktop.systemd1",
2558 "org.freedesktop.systemd1.Unit",
2564 /* systemd might have droppped off momentarily, let's
2565 * not make this an error */
2566 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2567 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2570 /* If the unit is already unloaded then it's not
2572 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2573 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2579 r = sd_bus_message_read(reply, "s", &state);
2583 return !streq(state, "inactive") && !streq(state, "failed");
2586 int manager_job_is_active(Manager *manager, const char *path) {
2587 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2588 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2594 r = sd_bus_get_property(
2596 "org.freedesktop.systemd1",
2598 "org.freedesktop.systemd1.Job",
2604 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2605 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2608 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2614 /* We don't actually care about the state really. The fact
2615 * that we could read the job state is enough for us */