1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "sd-messages.h"
30 #include "path-util.h"
32 #include "sleep-config.h"
33 #include "fileio-label.h"
34 #include "unit-name.h"
37 #include "bus-error.h"
38 #include "bus-common-errors.h"
39 #include "udev-util.h"
40 #include "selinux-util.h"
43 #include "formats-util.h"
44 #include "process-util.h"
45 #include "terminal-util.h"
47 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
48 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
57 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
61 r = sd_bus_creds_get_session(creds, &name);
66 session = hashmap_get(m->sessions, name);
68 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
74 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
82 if (uid == UID_INVALID) {
83 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
85 /* Note that we get the owner UID of the session, not the actual client UID here! */
86 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
90 r = sd_bus_creds_get_owner_uid(creds, &uid);
95 user = hashmap_get(m->users, UID_TO_PTR(uid));
97 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
103 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
114 r = manager_get_session_from_creds(m, message, NULL, error, &session);
118 seat = session->seat;
121 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
123 seat = hashmap_get(m->seats, name);
125 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
132 static int property_get_idle_hint(
135 const char *interface,
136 const char *property,
137 sd_bus_message *reply,
139 sd_bus_error *error) {
141 Manager *m = userdata;
147 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
150 static int property_get_idle_since_hint(
153 const char *interface,
154 const char *property,
155 sd_bus_message *reply,
157 sd_bus_error *error) {
159 Manager *m = userdata;
166 manager_get_idle_hint(m, &t);
168 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
171 static int property_get_inhibited(
174 const char *interface,
175 const char *property,
176 sd_bus_message *reply,
178 sd_bus_error *error) {
180 Manager *m = userdata;
187 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
189 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
192 static int property_get_preparing(
195 const char *interface,
196 const char *property,
197 sd_bus_message *reply,
199 sd_bus_error *error) {
201 Manager *m = userdata;
208 if (streq(property, "PreparingForShutdown"))
209 b = !!(m->action_what & INHIBIT_SHUTDOWN);
211 b = !!(m->action_what & INHIBIT_SLEEP);
213 return sd_bus_message_append(reply, "b", b);
216 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
218 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
219 _cleanup_free_ char *p = NULL;
220 Manager *m = userdata;
229 r = sd_bus_message_read(message, "s", &name);
233 r = manager_get_session_from_creds(m, message, name, error, &session);
237 p = session_bus_path(session);
241 return sd_bus_reply_method_return(message, "o", p);
244 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
245 _cleanup_free_ char *p = NULL;
246 Session *session = NULL;
247 Manager *m = userdata;
255 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
257 r = sd_bus_message_read(message, "u", &pid);
262 r = manager_get_session_from_creds(m, message, NULL, error, &session);
266 r = manager_get_session_by_pid(m, pid, &session);
271 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
274 p = session_bus_path(session);
278 return sd_bus_reply_method_return(message, "o", p);
281 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
282 _cleanup_free_ char *p = NULL;
283 Manager *m = userdata;
292 r = sd_bus_message_read(message, "u", &uid);
296 r = manager_get_user_from_creds(m, message, uid, error, &user);
300 p = user_bus_path(user);
304 return sd_bus_reply_method_return(message, "o", p);
307 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
308 _cleanup_free_ char *p = NULL;
309 Manager *m = userdata;
318 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
320 r = sd_bus_message_read(message, "u", &pid);
325 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
329 r = manager_get_user_by_pid(m, pid, &user);
333 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);
336 p = user_bus_path(user);
340 return sd_bus_reply_method_return(message, "o", p);
343 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
344 _cleanup_free_ char *p = NULL;
345 Manager *m = userdata;
354 r = sd_bus_message_read(message, "s", &name);
358 r = manager_get_seat_from_creds(m, message, name, error, &seat);
362 p = seat_bus_path(seat);
366 return sd_bus_reply_method_return(message, "o", p);
369 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
370 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
371 Manager *m = userdata;
380 r = sd_bus_message_new_method_return(message, &reply);
384 r = sd_bus_message_open_container(reply, 'a', "(susso)");
388 HASHMAP_FOREACH(session, m->sessions, i) {
389 _cleanup_free_ char *p = NULL;
391 p = session_bus_path(session);
395 r = sd_bus_message_append(reply, "(susso)",
397 (uint32_t) session->user->uid,
399 session->seat ? session->seat->id : "",
405 r = sd_bus_message_close_container(reply);
409 return sd_bus_send(bus, reply, NULL);
412 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
413 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
414 Manager *m = userdata;
423 r = sd_bus_message_new_method_return(message, &reply);
427 r = sd_bus_message_open_container(reply, 'a', "(uso)");
431 HASHMAP_FOREACH(user, m->users, i) {
432 _cleanup_free_ char *p = NULL;
434 p = user_bus_path(user);
438 r = sd_bus_message_append(reply, "(uso)",
439 (uint32_t) user->uid,
446 r = sd_bus_message_close_container(reply);
450 return sd_bus_send(bus, reply, NULL);
453 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
454 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
455 Manager *m = userdata;
464 r = sd_bus_message_new_method_return(message, &reply);
468 r = sd_bus_message_open_container(reply, 'a', "(so)");
472 HASHMAP_FOREACH(seat, m->seats, i) {
473 _cleanup_free_ char *p = NULL;
475 p = seat_bus_path(seat);
479 r = sd_bus_message_append(reply, "(so)", seat->id, p);
484 r = sd_bus_message_close_container(reply);
488 return sd_bus_send(bus, reply, NULL);
491 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
492 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
493 Manager *m = userdata;
494 Inhibitor *inhibitor;
498 r = sd_bus_message_new_method_return(message, &reply);
502 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
506 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
508 r = sd_bus_message_append(reply, "(ssssuu)",
509 strempty(inhibit_what_to_string(inhibitor->what)),
510 strempty(inhibitor->who),
511 strempty(inhibitor->why),
512 strempty(inhibit_mode_to_string(inhibitor->mode)),
513 (uint32_t) inhibitor->uid,
514 (uint32_t) inhibitor->pid);
519 r = sd_bus_message_close_container(reply);
523 return sd_bus_send(bus, reply, NULL);
526 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
527 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
528 uint32_t uid, leader, audit_id = 0;
529 _cleanup_free_ char *id = NULL;
530 Session *session = NULL;
531 Manager *m = userdata;
544 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
549 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
552 t = _SESSION_TYPE_INVALID;
554 t = session_type_from_string(type);
556 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
560 c = _SESSION_CLASS_INVALID;
562 c = session_class_from_string(class);
564 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
567 if (isempty(desktop))
570 if (!string_is_safe(desktop))
571 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
577 seat = hashmap_get(m->seats, cseat);
579 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
582 if (tty_is_vc(tty)) {
587 else if (seat != m->seat0)
588 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);
590 v = vtnr_from_tty(tty);
592 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
596 else if (vtnr != (uint32_t) v)
597 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
599 } else if (tty_is_console(tty)) {
603 else if (seat != m->seat0)
604 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
607 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
611 if (seat_has_vts(seat)) {
612 if (!vtnr || vtnr > 63)
613 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
616 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
620 r = sd_bus_message_enter_container(message, 'a', "(sv)");
624 if (t == _SESSION_TYPE_INVALID) {
625 if (!isempty(display))
627 else if (!isempty(tty))
630 t = SESSION_UNSPECIFIED;
633 if (c == _SESSION_CLASS_INVALID) {
634 if (t == SESSION_UNSPECIFIED)
635 c = SESSION_BACKGROUND;
641 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
643 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
647 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
652 manager_get_session_by_pid(m, leader, &session);
654 _cleanup_free_ char *path = NULL;
655 _cleanup_close_ int fifo_fd = -1;
657 /* Session already exists, client is probably
658 * something like "su" which changes uid but is still
659 * the same session */
661 fifo_fd = session_create_fifo(session);
665 path = session_bus_path(session);
669 log_debug("Sending reply about an existing session: "
670 "id=%s object_path=%s uid=%u runtime_path=%s "
671 "session_fd=%d seat=%s vtnr=%u",
674 (uint32_t) session->user->uid,
675 session->user->runtime_path,
677 session->seat ? session->seat->id : "",
678 (uint32_t) session->vtnr);
680 return sd_bus_reply_method_return(
684 session->user->runtime_path,
686 (uint32_t) session->user->uid,
687 session->seat ? session->seat->id : "",
688 (uint32_t) session->vtnr,
692 audit_session_from_pid(leader, &audit_id);
694 /* Keep our session IDs and the audit session IDs in sync */
696 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
699 /* Wut? There's already a session by this name and we
700 * didn't find it above? Weird, then let's not trust
701 * the audit data and let's better register a new
703 if (hashmap_get(m->sessions, id)) {
704 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
717 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
720 } while (hashmap_get(m->sessions, id));
723 r = manager_add_user_by_uid(m, uid, &user);
727 r = manager_add_session(m, id, &session);
731 session_set_user(session, user);
733 session->leader = leader;
734 session->audit_id = audit_id;
737 session->remote = remote;
738 session->vtnr = vtnr;
741 session->tty = strdup(tty);
748 if (!isempty(display)) {
749 session->display = strdup(display);
750 if (!session->display) {
756 if (!isempty(remote_user)) {
757 session->remote_user = strdup(remote_user);
758 if (!session->remote_user) {
764 if (!isempty(remote_host)) {
765 session->remote_host = strdup(remote_host);
766 if (!session->remote_host) {
772 if (!isempty(service)) {
773 session->service = strdup(service);
774 if (!session->service) {
780 if (!isempty(desktop)) {
781 session->desktop = strdup(desktop);
782 if (!session->desktop) {
789 r = seat_attach_session(seat, session);
794 r = session_start(session);
798 session->create_message = sd_bus_message_ref(message);
800 /* Now, let's wait until the slice unit and stuff got
801 * created. We send the reply back from
802 * session_send_create_reply(). */
808 session_add_to_gc_queue(session);
811 user_add_to_gc_queue(user);
816 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
817 Manager *m = userdata;
826 r = sd_bus_message_read(message, "s", &name);
830 r = manager_get_session_from_creds(m, message, name, error, &session);
834 r = session_release(session);
838 return sd_bus_reply_method_return(message, NULL);
841 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
842 Manager *m = userdata;
851 r = sd_bus_message_read(message, "s", &name);
855 r = manager_get_session_from_creds(m, message, name, error, &session);
859 return bus_session_method_activate(bus, message, session, error);
862 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
863 const char *session_name, *seat_name;
864 Manager *m = userdata;
873 /* Same as ActivateSession() but refuses to work if
874 * the seat doesn't match */
876 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
880 r = manager_get_session_from_creds(m, message, session_name, error, &session);
884 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
888 if (session->seat != seat)
889 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
891 r = session_activate(session);
895 return sd_bus_reply_method_return(message, NULL);
898 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
899 Manager *m = userdata;
908 r = sd_bus_message_read(message, "s", &name);
912 r = manager_get_session_from_creds(m, message, name, error, &session);
916 return bus_session_method_lock(bus, message, session, error);
919 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
920 Manager *m = userdata;
927 r = bus_verify_polkit_async(
930 "org.freedesktop.login1.lock-sessions",
938 return 1; /* Will call us back */
940 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
944 return sd_bus_reply_method_return(message, NULL);
947 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
949 Manager *m = userdata;
957 r = sd_bus_message_read(message, "s", &name);
961 r = manager_get_session_from_creds(m, message, name, error, &session);
965 return bus_session_method_kill(bus, message, session, error);
968 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
969 Manager *m = userdata;
978 r = sd_bus_message_read(message, "u", &uid);
982 r = manager_get_user_from_creds(m, message, uid, error, &user);
986 return bus_user_method_kill(bus, message, user, error);
989 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
990 Manager *m = userdata;
999 r = sd_bus_message_read(message, "s", &name);
1003 r = manager_get_session_from_creds(m, message, name, error, &session);
1007 return bus_session_method_terminate(bus, message, session, error);
1010 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1011 Manager *m = userdata;
1020 r = sd_bus_message_read(message, "u", &uid);
1024 r = manager_get_user_from_creds(m, message, uid, error, &user);
1028 return bus_user_method_terminate(bus, message, user, error);
1031 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1032 Manager *m = userdata;
1041 r = sd_bus_message_read(message, "s", &name);
1045 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1049 return bus_seat_method_terminate(bus, message, seat, error);
1052 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1053 _cleanup_free_ char *cc = NULL;
1054 Manager *m = userdata;
1065 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1069 if (uid == UID_INVALID) {
1070 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1072 /* Note that we get the owner UID of the session, not the actual client UID here! */
1073 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1077 r = sd_bus_creds_get_owner_uid(creds, &uid);
1085 return errno ? -errno : -ENOENT;
1087 r = bus_verify_polkit_async(
1090 "org.freedesktop.login1.set-user-linger",
1093 &m->polkit_registry,
1098 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1100 mkdir_p_label("/var/lib/systemd", 0755);
1102 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1106 cc = cescape(pw->pw_name);
1110 path = strjoina("/var/lib/systemd/linger/", cc);
1118 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1125 if (r < 0 && errno != ENOENT)
1128 u = hashmap_get(m->users, UID_TO_PTR(uid));
1130 user_add_to_gc_queue(u);
1133 return sd_bus_reply_method_return(message, NULL);
1136 static int trigger_device(Manager *m, struct udev_device *d) {
1137 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1138 struct udev_list_entry *first, *item;
1143 e = udev_enumerate_new(m->udev);
1148 r = udev_enumerate_add_match_parent(e, d);
1153 r = udev_enumerate_scan_devices(e);
1157 first = udev_enumerate_get_list_entry(e);
1158 udev_list_entry_foreach(item, first) {
1159 _cleanup_free_ char *t = NULL;
1162 p = udev_list_entry_get_name(item);
1164 t = strappend(p, "/uevent");
1168 write_string_file(t, "change");
1174 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1175 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1176 _cleanup_free_ char *rule = NULL, *file = NULL;
1177 const char *id_for_seat;
1184 d = udev_device_new_from_syspath(m->udev, sysfs);
1188 if (!udev_device_has_tag(d, "seat"))
1191 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1195 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1198 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1201 mkdir_p_label("/etc/udev/rules.d", 0755);
1202 mac_selinux_init("/etc");
1203 r = write_string_file_atomic_label(file, rule);
1207 return trigger_device(m, d);
1210 static int flush_devices(Manager *m) {
1211 _cleanup_closedir_ DIR *d;
1215 d = opendir("/etc/udev/rules.d");
1217 if (errno != ENOENT)
1218 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1222 while ((de = readdir(d))) {
1224 if (!dirent_is_file(de))
1227 if (!startswith(de->d_name, "72-seat-"))
1230 if (!endswith(de->d_name, ".rules"))
1233 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1234 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1238 return trigger_device(m, NULL);
1241 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1242 const char *sysfs, *seat;
1243 Manager *m = userdata;
1250 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1254 if (!path_startswith(sysfs, "/sys"))
1255 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1257 if (!seat_name_is_valid(seat))
1258 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1260 r = bus_verify_polkit_async(
1263 "org.freedesktop.login1.attach-device",
1266 &m->polkit_registry,
1271 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1273 r = attach_device(m, seat, sysfs);
1277 return sd_bus_reply_method_return(message, NULL);
1280 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1281 Manager *m = userdata;
1288 r = sd_bus_message_read(message, "b", &interactive);
1292 r = bus_verify_polkit_async(
1295 "org.freedesktop.login1.flush-devices",
1298 &m->polkit_registry,
1303 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1305 r = flush_devices(m);
1309 return sd_bus_reply_method_return(message, NULL);
1312 static int have_multiple_sessions(
1321 /* Check for other users' sessions. Greeter sessions do not
1322 * count, and non-login sessions do not count either. */
1323 HASHMAP_FOREACH(session, m->sessions, i)
1324 if (session->class == SESSION_USER &&
1325 session->user->uid != uid)
1331 static int bus_manager_log_shutdown(
1334 const char *unit_name) {
1341 if (w != INHIBIT_SHUTDOWN)
1344 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1345 p = "MESSAGE=System is powering down.";
1346 q = "SHUTDOWN=power-off";
1347 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1348 p = "MESSAGE=System is halting.";
1349 q = "SHUTDOWN=halt";
1350 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1351 p = "MESSAGE=System is rebooting.";
1352 q = "SHUTDOWN=reboot";
1353 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1354 p = "MESSAGE=System is rebooting with kexec.";
1355 q = "SHUTDOWN=kexec";
1357 p = "MESSAGE=System is shutting down.";
1361 return log_struct(LOG_NOTICE,
1362 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1368 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1369 Manager *m = userdata;
1374 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1378 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1383 if (until <= now(CLOCK_MONOTONIC))
1386 /* We want to ignore the lid switch for a while after each
1387 * suspend, and after boot-up. Hence let's install a timer for
1388 * this. As long as the event source exists we ignore the lid
1391 if (m->lid_switch_ignore_event_source) {
1394 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1401 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1403 r = sd_event_add_time(
1405 &m->lid_switch_ignore_event_source,
1408 lid_switch_ignore_handler, m);
1413 static int execute_shutdown_or_sleep(
1416 const char *unit_name,
1417 sd_bus_error *error) {
1419 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1426 assert(w < _INHIBIT_WHAT_MAX);
1429 bus_manager_log_shutdown(m, w, unit_name);
1431 r = sd_bus_call_method(
1433 "org.freedesktop.systemd1",
1434 "/org/freedesktop/systemd1",
1435 "org.freedesktop.systemd1.Manager",
1439 "ss", unit_name, "replace-irreversibly");
1443 r = sd_bus_message_read(reply, "o", &p);
1451 m->action_unit = unit_name;
1452 free(m->action_job);
1456 /* Make sure the lid switch is ignored for a while */
1457 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1462 static int manager_inhibit_timeout_handler(
1467 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1468 Inhibitor *offending = NULL;
1469 Manager *manager = userdata;
1473 assert(manager->inhibit_timeout_source == s);
1475 if (manager->action_what == 0 || manager->action_job)
1478 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1479 _cleanup_free_ char *comm = NULL, *u = NULL;
1481 (void) get_process_comm(offending->pid, &comm);
1482 u = uid_to_name(offending->uid);
1484 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1485 offending->uid, strna(u),
1486 offending->pid, strna(comm));
1489 /* Actually do the operation */
1490 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1492 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1494 manager->action_unit = NULL;
1495 manager->action_what = 0;
1501 static int delay_shutdown_or_sleep(
1504 const char *unit_name) {
1511 assert(w < _INHIBIT_WHAT_MAX);
1514 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1516 if (m->inhibit_timeout_source) {
1517 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1519 return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
1521 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1523 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
1525 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1526 timeout_val, 0, manager_inhibit_timeout_handler, m);
1531 m->action_unit = unit_name;
1537 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1539 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1540 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1541 [INHIBIT_SLEEP] = "PrepareForSleep"
1544 int active = _active;
1548 assert(w < _INHIBIT_WHAT_MAX);
1549 assert(signal_name[w]);
1551 return sd_bus_emit_signal(m->bus,
1552 "/org/freedesktop/login1",
1553 "org.freedesktop.login1.Manager",
1559 int bus_manager_shutdown_or_sleep_now_or_later(
1561 const char *unit_name,
1563 sd_bus_error *error) {
1571 assert(w <= _INHIBIT_WHAT_MAX);
1572 assert(!m->action_job);
1574 /* Tell everybody to prepare for shutdown/sleep */
1575 send_prepare_for(m, w, true);
1578 m->inhibit_delay_max > 0 &&
1579 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1582 /* Shutdown is delayed, keep in mind what we
1583 * want to do, and start a timeout */
1584 r = delay_shutdown_or_sleep(m, w, unit_name);
1586 /* Shutdown is not delayed, execute it
1588 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1593 static int method_do_shutdown_or_sleep(
1595 sd_bus_message *message,
1596 const char *unit_name,
1599 const char *action_multiple_sessions,
1600 const char *action_ignore_inhibit,
1601 const char *sleep_verb,
1602 sd_bus_message_handler_t method,
1603 sd_bus_error *error) {
1605 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1606 bool multiple_sessions, blocked;
1614 assert(w <= _INHIBIT_WHAT_MAX);
1616 assert(action_multiple_sessions);
1617 assert(action_ignore_inhibit);
1620 r = sd_bus_message_read(message, "b", &interactive);
1624 /* Don't allow multiple jobs being executed at the same time */
1626 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1629 r = can_sleep(sleep_verb);
1634 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1637 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1641 r = sd_bus_creds_get_euid(creds, &uid);
1645 r = have_multiple_sessions(m, uid);
1649 multiple_sessions = r > 0;
1650 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1652 if (multiple_sessions) {
1653 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1657 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1661 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1665 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1668 if (!multiple_sessions && !blocked) {
1669 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1673 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1676 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1680 return sd_bus_reply_method_return(message, NULL);
1683 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1684 Manager *m = userdata;
1686 return method_do_shutdown_or_sleep(
1688 SPECIAL_POWEROFF_TARGET,
1690 "org.freedesktop.login1.power-off",
1691 "org.freedesktop.login1.power-off-multiple-sessions",
1692 "org.freedesktop.login1.power-off-ignore-inhibit",
1698 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1699 Manager *m = userdata;
1701 return method_do_shutdown_or_sleep(
1703 SPECIAL_REBOOT_TARGET,
1705 "org.freedesktop.login1.reboot",
1706 "org.freedesktop.login1.reboot-multiple-sessions",
1707 "org.freedesktop.login1.reboot-ignore-inhibit",
1713 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1714 Manager *m = userdata;
1716 return method_do_shutdown_or_sleep(
1718 SPECIAL_SUSPEND_TARGET,
1720 "org.freedesktop.login1.suspend",
1721 "org.freedesktop.login1.suspend-multiple-sessions",
1722 "org.freedesktop.login1.suspend-ignore-inhibit",
1728 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1729 Manager *m = userdata;
1731 return method_do_shutdown_or_sleep(
1733 SPECIAL_HIBERNATE_TARGET,
1735 "org.freedesktop.login1.hibernate",
1736 "org.freedesktop.login1.hibernate-multiple-sessions",
1737 "org.freedesktop.login1.hibernate-ignore-inhibit",
1743 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1744 Manager *m = userdata;
1746 return method_do_shutdown_or_sleep(
1748 SPECIAL_HYBRID_SLEEP_TARGET,
1750 "org.freedesktop.login1.hibernate",
1751 "org.freedesktop.login1.hibernate-multiple-sessions",
1752 "org.freedesktop.login1.hibernate-ignore-inhibit",
1754 method_hybrid_sleep,
1758 static int method_can_shutdown_or_sleep(
1760 sd_bus_message *message,
1763 const char *action_multiple_sessions,
1764 const char *action_ignore_inhibit,
1765 const char *sleep_verb,
1766 sd_bus_error *error) {
1768 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1769 bool multiple_sessions, challenge, blocked;
1770 const char *result = NULL;
1777 assert(w <= _INHIBIT_WHAT_MAX);
1779 assert(action_multiple_sessions);
1780 assert(action_ignore_inhibit);
1783 r = can_sleep(sleep_verb);
1787 return sd_bus_reply_method_return(message, "s", "na");
1790 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1794 r = sd_bus_creds_get_euid(creds, &uid);
1798 r = have_multiple_sessions(m, uid);
1802 multiple_sessions = r > 0;
1803 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1805 if (multiple_sessions) {
1806 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
1813 result = "challenge";
1819 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
1823 if (r > 0 && !result)
1825 else if (challenge && (!result || streq(result, "yes")))
1826 result = "challenge";
1831 if (!multiple_sessions && !blocked) {
1832 /* If neither inhibit nor multiple sessions
1833 * apply then just check the normal policy */
1835 r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
1842 result = "challenge";
1847 return sd_bus_reply_method_return(message, "s", result);
1850 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1851 Manager *m = userdata;
1853 return method_can_shutdown_or_sleep(
1856 "org.freedesktop.login1.power-off",
1857 "org.freedesktop.login1.power-off-multiple-sessions",
1858 "org.freedesktop.login1.power-off-ignore-inhibit",
1863 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1864 Manager *m = userdata;
1866 return method_can_shutdown_or_sleep(
1869 "org.freedesktop.login1.reboot",
1870 "org.freedesktop.login1.reboot-multiple-sessions",
1871 "org.freedesktop.login1.reboot-ignore-inhibit",
1876 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1877 Manager *m = userdata;
1879 return method_can_shutdown_or_sleep(
1882 "org.freedesktop.login1.suspend",
1883 "org.freedesktop.login1.suspend-multiple-sessions",
1884 "org.freedesktop.login1.suspend-ignore-inhibit",
1889 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1890 Manager *m = userdata;
1892 return method_can_shutdown_or_sleep(
1895 "org.freedesktop.login1.hibernate",
1896 "org.freedesktop.login1.hibernate-multiple-sessions",
1897 "org.freedesktop.login1.hibernate-ignore-inhibit",
1902 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1903 Manager *m = userdata;
1905 return method_can_shutdown_or_sleep(
1908 "org.freedesktop.login1.hibernate",
1909 "org.freedesktop.login1.hibernate-multiple-sessions",
1910 "org.freedesktop.login1.hibernate-ignore-inhibit",
1915 static int property_get_reboot_to_firmware_setup(
1918 const char *interface,
1919 const char *property,
1920 sd_bus_message *reply,
1922 sd_bus_error *error) {
1929 r = efi_get_reboot_to_firmware();
1930 if (r < 0 && r != -EOPNOTSUPP)
1933 return sd_bus_message_append(reply, "b", r > 0);
1936 static int method_set_reboot_to_firmware_setup(
1938 sd_bus_message *message,
1940 sd_bus_error *error) {
1943 Manager *m = userdata;
1949 r = sd_bus_message_read(message, "b", &b);
1953 r = bus_verify_polkit_async(message,
1955 "org.freedesktop.login1.set-reboot-to-firmware-setup",
1958 &m->polkit_registry,
1963 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1965 r = efi_set_reboot_to_firmware(b);
1969 return sd_bus_reply_method_return(message, NULL);
1972 static int method_can_reboot_to_firmware_setup(
1974 sd_bus_message *message,
1976 sd_bus_error *error) {
1981 Manager *m = userdata;
1987 r = efi_reboot_to_firmware_supported();
1988 if (r == -EOPNOTSUPP)
1989 return sd_bus_reply_method_return(message, "s", "na");
1993 r = bus_test_polkit(message,
1995 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2005 result = "challenge";
2009 return sd_bus_reply_method_return(message, "s", result);
2012 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2013 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2014 const char *who, *why, *what, *mode;
2015 _cleanup_free_ char *id = NULL;
2016 _cleanup_close_ int fifo_fd = -1;
2017 Manager *m = userdata;
2018 Inhibitor *i = NULL;
2029 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2033 w = inhibit_what_from_string(what);
2035 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2037 mm = inhibit_mode_from_string(mode);
2039 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2041 /* Delay is only supported for shutdown/sleep */
2042 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2043 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2045 /* Don't allow taking delay locks while we are already
2046 * executing the operation. We shouldn't create the impression
2047 * that the lock was successful if the machine is about to go
2048 * down/suspend any moment. */
2049 if (m->action_what & w)
2050 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2052 r = bus_verify_polkit_async(
2055 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2056 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2057 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2058 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2059 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2060 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2061 "org.freedesktop.login1.inhibit-handle-lid-switch",
2064 &m->polkit_registry,
2069 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2071 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2075 r = sd_bus_creds_get_euid(creds, &uid);
2079 r = sd_bus_creds_get_pid(creds, &pid);
2087 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2090 } while (hashmap_get(m->inhibitors, id));
2092 r = manager_add_inhibitor(m, id, &i);
2100 i->why = strdup(why);
2101 i->who = strdup(who);
2103 if (!i->why || !i->who) {
2108 fifo_fd = inhibitor_create_fifo(i);
2116 return sd_bus_reply_method_return(message, "h", fifo_fd);
2125 const sd_bus_vtable manager_vtable[] = {
2126 SD_BUS_VTABLE_START(0),
2128 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2129 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2130 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2131 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2132 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2133 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2134 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2135 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2136 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2137 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2138 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2139 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2140 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2141 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2142 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2143 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2144 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2145 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2146 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2147 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2148 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2150 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2151 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2152 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2153 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2154 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2155 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2156 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2157 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2158 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2159 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2160 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2161 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2162 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2163 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2164 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2165 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2166 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2167 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2168 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2169 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2170 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2171 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2172 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2173 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2174 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2175 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2176 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2177 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2178 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2179 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2180 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2181 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2182 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2183 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2184 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2185 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2186 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2187 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2189 SD_BUS_SIGNAL("SessionNew", "so", 0),
2190 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2191 SD_BUS_SIGNAL("UserNew", "uo", 0),
2192 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2193 SD_BUS_SIGNAL("SeatNew", "so", 0),
2194 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2195 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2196 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2201 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2210 if (streq(result, "done"))
2211 r = session_send_create_reply(s, NULL);
2213 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2215 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2216 r = session_send_create_reply(s, &e);
2222 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2223 const char *path, *result, *unit;
2224 Manager *m = userdata;
2234 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2236 bus_log_parse_error(r);
2240 if (m->action_job && streq(m->action_job, path)) {
2241 log_info("Operation finished.");
2243 /* Tell people that they now may take a lock again */
2244 send_prepare_for(m, m->action_what, false);
2246 free(m->action_job);
2247 m->action_job = NULL;
2248 m->action_unit = NULL;
2253 session = hashmap_get(m->session_units, unit);
2256 if (streq_ptr(path, session->scope_job)) {
2257 free(session->scope_job);
2258 session->scope_job = NULL;
2261 session_jobs_reply(session, unit, result);
2263 session_save(session);
2264 session_add_to_gc_queue(session);
2267 user = hashmap_get(m->user_units, unit);
2270 if (streq_ptr(path, user->service_job)) {
2271 free(user->service_job);
2272 user->service_job = NULL;
2275 if (streq_ptr(path, user->slice_job)) {
2276 free(user->slice_job);
2277 user->slice_job = NULL;
2280 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2281 session_jobs_reply(session, unit, result);
2285 user_add_to_gc_queue(user);
2291 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2292 const char *path, *unit;
2293 Manager *m = userdata;
2302 r = sd_bus_message_read(message, "so", &unit, &path);
2304 bus_log_parse_error(r);
2308 session = hashmap_get(m->session_units, unit);
2310 session_add_to_gc_queue(session);
2312 user = hashmap_get(m->user_units, unit);
2314 user_add_to_gc_queue(user);
2319 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2320 _cleanup_free_ char *unit = NULL;
2321 Manager *m = userdata;
2331 path = sd_bus_message_get_path(message);
2335 r = unit_name_from_dbus_path(path, &unit);
2336 if (r == -EINVAL) /* not a unit */
2341 session = hashmap_get(m->session_units, unit);
2343 session_add_to_gc_queue(session);
2345 user = hashmap_get(m->user_units, unit);
2347 user_add_to_gc_queue(user);
2352 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2353 Manager *m = userdata;
2360 r = sd_bus_message_read(message, "b", &b);
2362 bus_log_parse_error(r);
2369 /* systemd finished reloading, let's recheck all our sessions */
2370 log_debug("System manager has been reloaded, rechecking sessions...");
2372 HASHMAP_FOREACH(session, m->sessions, i)
2373 session_add_to_gc_queue(session);
2378 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2379 const char *name, *old, *new;
2380 Manager *m = userdata;
2388 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2390 bus_log_parse_error(r);
2394 if (isempty(old) || !isempty(new))
2397 key = set_remove(m->busnames, (char*) old);
2401 /* Drop all controllers owned by this name */
2405 HASHMAP_FOREACH(session, m->sessions, i)
2406 if (session_is_controller(session, old))
2407 session_drop_controller(session);
2412 int manager_send_changed(Manager *manager, const char *property, ...) {
2417 l = strv_from_stdarg_alloca(property);
2419 return sd_bus_emit_properties_changed_strv(
2421 "/org/freedesktop/login1",
2422 "org.freedesktop.login1.Manager",
2426 int manager_start_scope(
2431 const char *description,
2432 const char *after, const char *after2,
2433 sd_bus_error *error,
2436 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2443 r = sd_bus_message_new_method_call(
2446 "org.freedesktop.systemd1",
2447 "/org/freedesktop/systemd1",
2448 "org.freedesktop.systemd1.Manager",
2449 "StartTransientUnit");
2453 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2457 r = sd_bus_message_open_container(m, 'a', "(sv)");
2461 if (!isempty(slice)) {
2462 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2467 if (!isempty(description)) {
2468 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2473 if (!isempty(after)) {
2474 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2479 if (!isempty(after2)) {
2480 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2485 /* cgroup empty notification is not available in containers
2486 * currently. To make this less problematic, let's shorten the
2487 * stop timeout for sessions, so that we don't wait
2490 /* Make sure that the session shells are terminated with
2491 * SIGHUP since bash and friends tend to ignore SIGTERM */
2492 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2496 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2500 r = sd_bus_message_close_container(m);
2504 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2508 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2516 r = sd_bus_message_read(reply, "o", &j);
2530 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2531 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2537 r = sd_bus_call_method(
2539 "org.freedesktop.systemd1",
2540 "/org/freedesktop/systemd1",
2541 "org.freedesktop.systemd1.Manager",
2545 "ss", unit, "fail");
2553 r = sd_bus_message_read(reply, "o", &j);
2567 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2568 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2574 r = sd_bus_call_method(
2576 "org.freedesktop.systemd1",
2577 "/org/freedesktop/systemd1",
2578 "org.freedesktop.systemd1.Manager",
2582 "ss", unit, "fail");
2584 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2585 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2590 sd_bus_error_free(error);
2601 r = sd_bus_message_read(reply, "o", &j);
2615 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2616 _cleanup_free_ char *path = NULL;
2622 path = unit_dbus_path_from_name(scope);
2626 r = sd_bus_call_method(
2628 "org.freedesktop.systemd1",
2630 "org.freedesktop.systemd1.Scope",
2636 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2637 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2638 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2639 sd_bus_error_free(error);
2649 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2653 return sd_bus_call_method(
2655 "org.freedesktop.systemd1",
2656 "/org/freedesktop/systemd1",
2657 "org.freedesktop.systemd1.Manager",
2661 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2664 int manager_unit_is_active(Manager *manager, const char *unit) {
2665 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2666 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2667 _cleanup_free_ char *path = NULL;
2674 path = unit_dbus_path_from_name(unit);
2678 r = sd_bus_get_property(
2680 "org.freedesktop.systemd1",
2682 "org.freedesktop.systemd1.Unit",
2688 /* systemd might have droppped off momentarily, let's
2689 * not make this an error */
2690 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2691 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2694 /* If the unit is already unloaded then it's not
2696 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2697 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2703 r = sd_bus_message_read(reply, "s", &state);
2707 return !streq(state, "inactive") && !streq(state, "failed");
2710 int manager_job_is_active(Manager *manager, const char *path) {
2711 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2712 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2718 r = sd_bus_get_property(
2720 "org.freedesktop.systemd1",
2722 "org.freedesktop.systemd1.Job",
2728 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2729 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2732 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2738 /* We don't actually care about the state really. The fact
2739 * that we could read the job state is enough for us */