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 verify_shutdown_creds(
1595 sd_bus_message *message,
1599 const char *action_multiple_sessions,
1600 const char *action_ignore_inhibit,
1601 sd_bus_error *error) {
1603 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1604 bool multiple_sessions, blocked;
1611 assert(w <= _INHIBIT_WHAT_MAX);
1613 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1617 r = sd_bus_creds_get_euid(creds, &uid);
1621 r = have_multiple_sessions(m, uid);
1625 multiple_sessions = r > 0;
1626 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1628 if (multiple_sessions && action_multiple_sessions) {
1629 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1633 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1636 if (blocked && action_ignore_inhibit) {
1637 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1641 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1644 if (!multiple_sessions && !blocked && action) {
1645 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1649 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1655 static int method_do_shutdown_or_sleep(
1657 sd_bus_message *message,
1658 const char *unit_name,
1661 const char *action_multiple_sessions,
1662 const char *action_ignore_inhibit,
1663 const char *sleep_verb,
1664 sd_bus_error *error) {
1672 assert(w <= _INHIBIT_WHAT_MAX);
1674 r = sd_bus_message_read(message, "b", &interactive);
1678 /* Don't allow multiple jobs being executed at the same time */
1680 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1683 r = can_sleep(sleep_verb);
1688 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1691 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1692 action_ignore_inhibit, error);
1696 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1700 return sd_bus_reply_method_return(message, NULL);
1703 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1704 Manager *m = userdata;
1706 return method_do_shutdown_or_sleep(
1708 SPECIAL_POWEROFF_TARGET,
1710 "org.freedesktop.login1.power-off",
1711 "org.freedesktop.login1.power-off-multiple-sessions",
1712 "org.freedesktop.login1.power-off-ignore-inhibit",
1717 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1718 Manager *m = userdata;
1720 return method_do_shutdown_or_sleep(
1722 SPECIAL_REBOOT_TARGET,
1724 "org.freedesktop.login1.reboot",
1725 "org.freedesktop.login1.reboot-multiple-sessions",
1726 "org.freedesktop.login1.reboot-ignore-inhibit",
1731 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1732 Manager *m = userdata;
1734 return method_do_shutdown_or_sleep(
1736 SPECIAL_SUSPEND_TARGET,
1738 "org.freedesktop.login1.suspend",
1739 "org.freedesktop.login1.suspend-multiple-sessions",
1740 "org.freedesktop.login1.suspend-ignore-inhibit",
1745 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1746 Manager *m = userdata;
1748 return method_do_shutdown_or_sleep(
1750 SPECIAL_HIBERNATE_TARGET,
1752 "org.freedesktop.login1.hibernate",
1753 "org.freedesktop.login1.hibernate-multiple-sessions",
1754 "org.freedesktop.login1.hibernate-ignore-inhibit",
1759 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1760 Manager *m = userdata;
1762 return method_do_shutdown_or_sleep(
1764 SPECIAL_HYBRID_SLEEP_TARGET,
1766 "org.freedesktop.login1.hibernate",
1767 "org.freedesktop.login1.hibernate-multiple-sessions",
1768 "org.freedesktop.login1.hibernate-ignore-inhibit",
1773 static int method_can_shutdown_or_sleep(
1775 sd_bus_message *message,
1778 const char *action_multiple_sessions,
1779 const char *action_ignore_inhibit,
1780 const char *sleep_verb,
1781 sd_bus_error *error) {
1783 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1784 bool multiple_sessions, challenge, blocked;
1785 const char *result = NULL;
1792 assert(w <= _INHIBIT_WHAT_MAX);
1794 assert(action_multiple_sessions);
1795 assert(action_ignore_inhibit);
1798 r = can_sleep(sleep_verb);
1802 return sd_bus_reply_method_return(message, "s", "na");
1805 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1809 r = sd_bus_creds_get_euid(creds, &uid);
1813 r = have_multiple_sessions(m, uid);
1817 multiple_sessions = r > 0;
1818 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1820 if (multiple_sessions) {
1821 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
1828 result = "challenge";
1834 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
1838 if (r > 0 && !result)
1840 else if (challenge && (!result || streq(result, "yes")))
1841 result = "challenge";
1846 if (!multiple_sessions && !blocked) {
1847 /* If neither inhibit nor multiple sessions
1848 * apply then just check the normal policy */
1850 r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
1857 result = "challenge";
1862 return sd_bus_reply_method_return(message, "s", result);
1865 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1866 Manager *m = userdata;
1868 return method_can_shutdown_or_sleep(
1871 "org.freedesktop.login1.power-off",
1872 "org.freedesktop.login1.power-off-multiple-sessions",
1873 "org.freedesktop.login1.power-off-ignore-inhibit",
1878 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1879 Manager *m = userdata;
1881 return method_can_shutdown_or_sleep(
1884 "org.freedesktop.login1.reboot",
1885 "org.freedesktop.login1.reboot-multiple-sessions",
1886 "org.freedesktop.login1.reboot-ignore-inhibit",
1891 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1892 Manager *m = userdata;
1894 return method_can_shutdown_or_sleep(
1897 "org.freedesktop.login1.suspend",
1898 "org.freedesktop.login1.suspend-multiple-sessions",
1899 "org.freedesktop.login1.suspend-ignore-inhibit",
1904 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1905 Manager *m = userdata;
1907 return method_can_shutdown_or_sleep(
1910 "org.freedesktop.login1.hibernate",
1911 "org.freedesktop.login1.hibernate-multiple-sessions",
1912 "org.freedesktop.login1.hibernate-ignore-inhibit",
1917 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1918 Manager *m = userdata;
1920 return method_can_shutdown_or_sleep(
1923 "org.freedesktop.login1.hibernate",
1924 "org.freedesktop.login1.hibernate-multiple-sessions",
1925 "org.freedesktop.login1.hibernate-ignore-inhibit",
1930 static int property_get_reboot_to_firmware_setup(
1933 const char *interface,
1934 const char *property,
1935 sd_bus_message *reply,
1937 sd_bus_error *error) {
1944 r = efi_get_reboot_to_firmware();
1945 if (r < 0 && r != -EOPNOTSUPP)
1948 return sd_bus_message_append(reply, "b", r > 0);
1951 static int method_set_reboot_to_firmware_setup(
1953 sd_bus_message *message,
1955 sd_bus_error *error) {
1958 Manager *m = userdata;
1964 r = sd_bus_message_read(message, "b", &b);
1968 r = bus_verify_polkit_async(message,
1970 "org.freedesktop.login1.set-reboot-to-firmware-setup",
1973 &m->polkit_registry,
1978 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1980 r = efi_set_reboot_to_firmware(b);
1984 return sd_bus_reply_method_return(message, NULL);
1987 static int method_can_reboot_to_firmware_setup(
1989 sd_bus_message *message,
1991 sd_bus_error *error) {
1996 Manager *m = userdata;
2002 r = efi_reboot_to_firmware_supported();
2003 if (r == -EOPNOTSUPP)
2004 return sd_bus_reply_method_return(message, "s", "na");
2008 r = bus_test_polkit(message,
2010 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2020 result = "challenge";
2024 return sd_bus_reply_method_return(message, "s", result);
2027 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2028 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2029 const char *who, *why, *what, *mode;
2030 _cleanup_free_ char *id = NULL;
2031 _cleanup_close_ int fifo_fd = -1;
2032 Manager *m = userdata;
2033 Inhibitor *i = NULL;
2044 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2048 w = inhibit_what_from_string(what);
2050 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2052 mm = inhibit_mode_from_string(mode);
2054 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2056 /* Delay is only supported for shutdown/sleep */
2057 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2058 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2060 /* Don't allow taking delay locks while we are already
2061 * executing the operation. We shouldn't create the impression
2062 * that the lock was successful if the machine is about to go
2063 * down/suspend any moment. */
2064 if (m->action_what & w)
2065 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2067 r = bus_verify_polkit_async(
2070 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2071 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2072 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2073 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2074 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2075 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2076 "org.freedesktop.login1.inhibit-handle-lid-switch",
2079 &m->polkit_registry,
2084 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2086 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2090 r = sd_bus_creds_get_euid(creds, &uid);
2094 r = sd_bus_creds_get_pid(creds, &pid);
2102 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2105 } while (hashmap_get(m->inhibitors, id));
2107 r = manager_add_inhibitor(m, id, &i);
2115 i->why = strdup(why);
2116 i->who = strdup(who);
2118 if (!i->why || !i->who) {
2123 fifo_fd = inhibitor_create_fifo(i);
2131 return sd_bus_reply_method_return(message, "h", fifo_fd);
2140 const sd_bus_vtable manager_vtable[] = {
2141 SD_BUS_VTABLE_START(0),
2143 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2144 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2145 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2146 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2147 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2148 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2149 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2150 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2151 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2152 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2153 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2154 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2155 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2156 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2157 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2158 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2159 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2160 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2161 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2162 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2163 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2165 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2166 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2167 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2168 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2169 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2170 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2171 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2172 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2173 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2174 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2175 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2176 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2177 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2178 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2179 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2180 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2181 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2182 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2183 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2184 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2185 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2186 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2187 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2188 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2189 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2190 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2191 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2192 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2193 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2194 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2195 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2196 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2197 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2198 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2199 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2200 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2201 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2202 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2204 SD_BUS_SIGNAL("SessionNew", "so", 0),
2205 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2206 SD_BUS_SIGNAL("UserNew", "uo", 0),
2207 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2208 SD_BUS_SIGNAL("SeatNew", "so", 0),
2209 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2210 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2211 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2216 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2225 if (streq(result, "done"))
2226 r = session_send_create_reply(s, NULL);
2228 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2230 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2231 r = session_send_create_reply(s, &e);
2237 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2238 const char *path, *result, *unit;
2239 Manager *m = userdata;
2249 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2251 bus_log_parse_error(r);
2255 if (m->action_job && streq(m->action_job, path)) {
2256 log_info("Operation finished.");
2258 /* Tell people that they now may take a lock again */
2259 send_prepare_for(m, m->action_what, false);
2261 free(m->action_job);
2262 m->action_job = NULL;
2263 m->action_unit = NULL;
2268 session = hashmap_get(m->session_units, unit);
2271 if (streq_ptr(path, session->scope_job)) {
2272 free(session->scope_job);
2273 session->scope_job = NULL;
2276 session_jobs_reply(session, unit, result);
2278 session_save(session);
2279 session_add_to_gc_queue(session);
2282 user = hashmap_get(m->user_units, unit);
2285 if (streq_ptr(path, user->service_job)) {
2286 free(user->service_job);
2287 user->service_job = NULL;
2290 if (streq_ptr(path, user->slice_job)) {
2291 free(user->slice_job);
2292 user->slice_job = NULL;
2295 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2296 session_jobs_reply(session, unit, result);
2300 user_add_to_gc_queue(user);
2306 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2307 const char *path, *unit;
2308 Manager *m = userdata;
2317 r = sd_bus_message_read(message, "so", &unit, &path);
2319 bus_log_parse_error(r);
2323 session = hashmap_get(m->session_units, unit);
2325 session_add_to_gc_queue(session);
2327 user = hashmap_get(m->user_units, unit);
2329 user_add_to_gc_queue(user);
2334 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2335 _cleanup_free_ char *unit = NULL;
2336 Manager *m = userdata;
2346 path = sd_bus_message_get_path(message);
2350 r = unit_name_from_dbus_path(path, &unit);
2351 if (r == -EINVAL) /* not a unit */
2356 session = hashmap_get(m->session_units, unit);
2358 session_add_to_gc_queue(session);
2360 user = hashmap_get(m->user_units, unit);
2362 user_add_to_gc_queue(user);
2367 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2368 Manager *m = userdata;
2375 r = sd_bus_message_read(message, "b", &b);
2377 bus_log_parse_error(r);
2384 /* systemd finished reloading, let's recheck all our sessions */
2385 log_debug("System manager has been reloaded, rechecking sessions...");
2387 HASHMAP_FOREACH(session, m->sessions, i)
2388 session_add_to_gc_queue(session);
2393 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2394 const char *name, *old, *new;
2395 Manager *m = userdata;
2403 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2405 bus_log_parse_error(r);
2409 if (isempty(old) || !isempty(new))
2412 key = set_remove(m->busnames, (char*) old);
2416 /* Drop all controllers owned by this name */
2420 HASHMAP_FOREACH(session, m->sessions, i)
2421 if (session_is_controller(session, old))
2422 session_drop_controller(session);
2427 int manager_send_changed(Manager *manager, const char *property, ...) {
2432 l = strv_from_stdarg_alloca(property);
2434 return sd_bus_emit_properties_changed_strv(
2436 "/org/freedesktop/login1",
2437 "org.freedesktop.login1.Manager",
2441 int manager_start_scope(
2446 const char *description,
2447 const char *after, const char *after2,
2448 sd_bus_error *error,
2451 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2458 r = sd_bus_message_new_method_call(
2461 "org.freedesktop.systemd1",
2462 "/org/freedesktop/systemd1",
2463 "org.freedesktop.systemd1.Manager",
2464 "StartTransientUnit");
2468 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2472 r = sd_bus_message_open_container(m, 'a', "(sv)");
2476 if (!isempty(slice)) {
2477 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2482 if (!isempty(description)) {
2483 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2488 if (!isempty(after)) {
2489 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2494 if (!isempty(after2)) {
2495 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2500 /* cgroup empty notification is not available in containers
2501 * currently. To make this less problematic, let's shorten the
2502 * stop timeout for sessions, so that we don't wait
2505 /* Make sure that the session shells are terminated with
2506 * SIGHUP since bash and friends tend to ignore SIGTERM */
2507 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2511 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2515 r = sd_bus_message_close_container(m);
2519 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2523 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2531 r = sd_bus_message_read(reply, "o", &j);
2545 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2546 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2552 r = sd_bus_call_method(
2554 "org.freedesktop.systemd1",
2555 "/org/freedesktop/systemd1",
2556 "org.freedesktop.systemd1.Manager",
2560 "ss", unit, "fail");
2568 r = sd_bus_message_read(reply, "o", &j);
2582 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2583 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2589 r = sd_bus_call_method(
2591 "org.freedesktop.systemd1",
2592 "/org/freedesktop/systemd1",
2593 "org.freedesktop.systemd1.Manager",
2597 "ss", unit, "fail");
2599 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2600 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2605 sd_bus_error_free(error);
2616 r = sd_bus_message_read(reply, "o", &j);
2630 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2631 _cleanup_free_ char *path = NULL;
2637 path = unit_dbus_path_from_name(scope);
2641 r = sd_bus_call_method(
2643 "org.freedesktop.systemd1",
2645 "org.freedesktop.systemd1.Scope",
2651 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2652 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2653 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2654 sd_bus_error_free(error);
2664 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2668 return sd_bus_call_method(
2670 "org.freedesktop.systemd1",
2671 "/org/freedesktop/systemd1",
2672 "org.freedesktop.systemd1.Manager",
2676 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2679 int manager_unit_is_active(Manager *manager, const char *unit) {
2680 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2681 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2682 _cleanup_free_ char *path = NULL;
2689 path = unit_dbus_path_from_name(unit);
2693 r = sd_bus_get_property(
2695 "org.freedesktop.systemd1",
2697 "org.freedesktop.systemd1.Unit",
2703 /* systemd might have droppped off momentarily, let's
2704 * not make this an error */
2705 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2706 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2709 /* If the unit is already unloaded then it's not
2711 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2712 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2718 r = sd_bus_message_read(reply, "s", &state);
2722 return !streq(state, "inactive") && !streq(state, "failed");
2725 int manager_job_is_active(Manager *manager, const char *path) {
2726 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2727 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2733 r = sd_bus_get_property(
2735 "org.freedesktop.systemd1",
2737 "org.freedesktop.systemd1.Job",
2743 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2744 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2747 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2753 /* We don't actually care about the state really. The fact
2754 * that we could read the job state is enough for us */