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 int property_get_scheduled_shutdown(
219 const char *interface,
220 const char *property,
221 sd_bus_message *reply,
223 sd_bus_error *error) {
225 Manager *m = userdata;
232 r = sd_bus_message_open_container(reply, 'r', "st");
236 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
240 return sd_bus_message_close_container(reply);
243 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
245 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
246 _cleanup_free_ char *p = NULL;
247 Manager *m = userdata;
256 r = sd_bus_message_read(message, "s", &name);
260 r = manager_get_session_from_creds(m, message, name, error, &session);
264 p = session_bus_path(session);
268 return sd_bus_reply_method_return(message, "o", p);
271 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
272 _cleanup_free_ char *p = NULL;
273 Session *session = NULL;
274 Manager *m = userdata;
282 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
284 r = sd_bus_message_read(message, "u", &pid);
289 r = manager_get_session_from_creds(m, message, NULL, error, &session);
293 r = manager_get_session_by_pid(m, pid, &session);
298 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
301 p = session_bus_path(session);
305 return sd_bus_reply_method_return(message, "o", p);
308 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
309 _cleanup_free_ char *p = NULL;
310 Manager *m = userdata;
319 r = sd_bus_message_read(message, "u", &uid);
323 r = manager_get_user_from_creds(m, message, uid, error, &user);
327 p = user_bus_path(user);
331 return sd_bus_reply_method_return(message, "o", p);
334 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
335 _cleanup_free_ char *p = NULL;
336 Manager *m = userdata;
345 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
347 r = sd_bus_message_read(message, "u", &pid);
352 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
356 r = manager_get_user_by_pid(m, pid, &user);
360 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);
363 p = user_bus_path(user);
367 return sd_bus_reply_method_return(message, "o", p);
370 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
371 _cleanup_free_ char *p = NULL;
372 Manager *m = userdata;
381 r = sd_bus_message_read(message, "s", &name);
385 r = manager_get_seat_from_creds(m, message, name, error, &seat);
389 p = seat_bus_path(seat);
393 return sd_bus_reply_method_return(message, "o", p);
396 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
397 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
398 Manager *m = userdata;
407 r = sd_bus_message_new_method_return(message, &reply);
411 r = sd_bus_message_open_container(reply, 'a', "(susso)");
415 HASHMAP_FOREACH(session, m->sessions, i) {
416 _cleanup_free_ char *p = NULL;
418 p = session_bus_path(session);
422 r = sd_bus_message_append(reply, "(susso)",
424 (uint32_t) session->user->uid,
426 session->seat ? session->seat->id : "",
432 r = sd_bus_message_close_container(reply);
436 return sd_bus_send(bus, reply, NULL);
439 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
440 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
441 Manager *m = userdata;
450 r = sd_bus_message_new_method_return(message, &reply);
454 r = sd_bus_message_open_container(reply, 'a', "(uso)");
458 HASHMAP_FOREACH(user, m->users, i) {
459 _cleanup_free_ char *p = NULL;
461 p = user_bus_path(user);
465 r = sd_bus_message_append(reply, "(uso)",
466 (uint32_t) user->uid,
473 r = sd_bus_message_close_container(reply);
477 return sd_bus_send(bus, reply, NULL);
480 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
481 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
482 Manager *m = userdata;
491 r = sd_bus_message_new_method_return(message, &reply);
495 r = sd_bus_message_open_container(reply, 'a', "(so)");
499 HASHMAP_FOREACH(seat, m->seats, i) {
500 _cleanup_free_ char *p = NULL;
502 p = seat_bus_path(seat);
506 r = sd_bus_message_append(reply, "(so)", seat->id, p);
511 r = sd_bus_message_close_container(reply);
515 return sd_bus_send(bus, reply, NULL);
518 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
519 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
520 Manager *m = userdata;
521 Inhibitor *inhibitor;
525 r = sd_bus_message_new_method_return(message, &reply);
529 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
533 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
535 r = sd_bus_message_append(reply, "(ssssuu)",
536 strempty(inhibit_what_to_string(inhibitor->what)),
537 strempty(inhibitor->who),
538 strempty(inhibitor->why),
539 strempty(inhibit_mode_to_string(inhibitor->mode)),
540 (uint32_t) inhibitor->uid,
541 (uint32_t) inhibitor->pid);
546 r = sd_bus_message_close_container(reply);
550 return sd_bus_send(bus, reply, NULL);
553 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
554 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
555 uint32_t uid, leader, audit_id = 0;
556 _cleanup_free_ char *id = NULL;
557 Session *session = NULL;
558 Manager *m = userdata;
571 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
576 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
579 t = _SESSION_TYPE_INVALID;
581 t = session_type_from_string(type);
583 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
587 c = _SESSION_CLASS_INVALID;
589 c = session_class_from_string(class);
591 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
594 if (isempty(desktop))
597 if (!string_is_safe(desktop))
598 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
604 seat = hashmap_get(m->seats, cseat);
606 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
609 if (tty_is_vc(tty)) {
614 else if (seat != m->seat0)
615 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);
617 v = vtnr_from_tty(tty);
619 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
623 else if (vtnr != (uint32_t) v)
624 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
626 } else if (tty_is_console(tty)) {
630 else if (seat != m->seat0)
631 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
634 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
638 if (seat_has_vts(seat)) {
639 if (!vtnr || vtnr > 63)
640 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
643 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
647 r = sd_bus_message_enter_container(message, 'a', "(sv)");
651 if (t == _SESSION_TYPE_INVALID) {
652 if (!isempty(display))
654 else if (!isempty(tty))
657 t = SESSION_UNSPECIFIED;
660 if (c == _SESSION_CLASS_INVALID) {
661 if (t == SESSION_UNSPECIFIED)
662 c = SESSION_BACKGROUND;
668 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
670 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
674 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
679 manager_get_session_by_pid(m, leader, &session);
681 _cleanup_free_ char *path = NULL;
682 _cleanup_close_ int fifo_fd = -1;
684 /* Session already exists, client is probably
685 * something like "su" which changes uid but is still
686 * the same session */
688 fifo_fd = session_create_fifo(session);
692 path = session_bus_path(session);
696 log_debug("Sending reply about an existing session: "
697 "id=%s object_path=%s uid=%u runtime_path=%s "
698 "session_fd=%d seat=%s vtnr=%u",
701 (uint32_t) session->user->uid,
702 session->user->runtime_path,
704 session->seat ? session->seat->id : "",
705 (uint32_t) session->vtnr);
707 return sd_bus_reply_method_return(
711 session->user->runtime_path,
713 (uint32_t) session->user->uid,
714 session->seat ? session->seat->id : "",
715 (uint32_t) session->vtnr,
719 audit_session_from_pid(leader, &audit_id);
721 /* Keep our session IDs and the audit session IDs in sync */
723 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
726 /* Wut? There's already a session by this name and we
727 * didn't find it above? Weird, then let's not trust
728 * the audit data and let's better register a new
730 if (hashmap_get(m->sessions, id)) {
731 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
744 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
747 } while (hashmap_get(m->sessions, id));
750 r = manager_add_user_by_uid(m, uid, &user);
754 r = manager_add_session(m, id, &session);
758 session_set_user(session, user);
760 session->leader = leader;
761 session->audit_id = audit_id;
764 session->remote = remote;
765 session->vtnr = vtnr;
768 session->tty = strdup(tty);
775 if (!isempty(display)) {
776 session->display = strdup(display);
777 if (!session->display) {
783 if (!isempty(remote_user)) {
784 session->remote_user = strdup(remote_user);
785 if (!session->remote_user) {
791 if (!isempty(remote_host)) {
792 session->remote_host = strdup(remote_host);
793 if (!session->remote_host) {
799 if (!isempty(service)) {
800 session->service = strdup(service);
801 if (!session->service) {
807 if (!isempty(desktop)) {
808 session->desktop = strdup(desktop);
809 if (!session->desktop) {
816 r = seat_attach_session(seat, session);
821 r = session_start(session);
825 session->create_message = sd_bus_message_ref(message);
827 /* Now, let's wait until the slice unit and stuff got
828 * created. We send the reply back from
829 * session_send_create_reply(). */
835 session_add_to_gc_queue(session);
838 user_add_to_gc_queue(user);
843 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
844 Manager *m = userdata;
853 r = sd_bus_message_read(message, "s", &name);
857 r = manager_get_session_from_creds(m, message, name, error, &session);
861 r = session_release(session);
865 return sd_bus_reply_method_return(message, NULL);
868 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
869 Manager *m = userdata;
878 r = sd_bus_message_read(message, "s", &name);
882 r = manager_get_session_from_creds(m, message, name, error, &session);
886 return bus_session_method_activate(bus, message, session, error);
889 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
890 const char *session_name, *seat_name;
891 Manager *m = userdata;
900 /* Same as ActivateSession() but refuses to work if
901 * the seat doesn't match */
903 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
907 r = manager_get_session_from_creds(m, message, session_name, error, &session);
911 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
915 if (session->seat != seat)
916 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
918 r = session_activate(session);
922 return sd_bus_reply_method_return(message, NULL);
925 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
926 Manager *m = userdata;
935 r = sd_bus_message_read(message, "s", &name);
939 r = manager_get_session_from_creds(m, message, name, error, &session);
943 return bus_session_method_lock(bus, message, session, error);
946 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
947 Manager *m = userdata;
954 r = bus_verify_polkit_async(
957 "org.freedesktop.login1.lock-sessions",
965 return 1; /* Will call us back */
967 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
971 return sd_bus_reply_method_return(message, NULL);
974 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
976 Manager *m = userdata;
984 r = sd_bus_message_read(message, "s", &name);
988 r = manager_get_session_from_creds(m, message, name, error, &session);
992 return bus_session_method_kill(bus, message, session, error);
995 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
996 Manager *m = userdata;
1005 r = sd_bus_message_read(message, "u", &uid);
1009 r = manager_get_user_from_creds(m, message, uid, error, &user);
1013 return bus_user_method_kill(bus, message, user, error);
1016 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1017 Manager *m = userdata;
1026 r = sd_bus_message_read(message, "s", &name);
1030 r = manager_get_session_from_creds(m, message, name, error, &session);
1034 return bus_session_method_terminate(bus, message, session, error);
1037 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1038 Manager *m = userdata;
1047 r = sd_bus_message_read(message, "u", &uid);
1051 r = manager_get_user_from_creds(m, message, uid, error, &user);
1055 return bus_user_method_terminate(bus, message, user, error);
1058 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1059 Manager *m = userdata;
1068 r = sd_bus_message_read(message, "s", &name);
1072 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1076 return bus_seat_method_terminate(bus, message, seat, error);
1079 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1080 _cleanup_free_ char *cc = NULL;
1081 Manager *m = userdata;
1092 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1096 if (uid == UID_INVALID) {
1097 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1099 /* Note that we get the owner UID of the session, not the actual client UID here! */
1100 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1104 r = sd_bus_creds_get_owner_uid(creds, &uid);
1112 return errno ? -errno : -ENOENT;
1114 r = bus_verify_polkit_async(
1117 "org.freedesktop.login1.set-user-linger",
1120 &m->polkit_registry,
1125 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1127 mkdir_p_label("/var/lib/systemd", 0755);
1129 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1133 cc = cescape(pw->pw_name);
1137 path = strjoina("/var/lib/systemd/linger/", cc);
1145 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1152 if (r < 0 && errno != ENOENT)
1155 u = hashmap_get(m->users, UID_TO_PTR(uid));
1157 user_add_to_gc_queue(u);
1160 return sd_bus_reply_method_return(message, NULL);
1163 static int trigger_device(Manager *m, struct udev_device *d) {
1164 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1165 struct udev_list_entry *first, *item;
1170 e = udev_enumerate_new(m->udev);
1175 r = udev_enumerate_add_match_parent(e, d);
1180 r = udev_enumerate_scan_devices(e);
1184 first = udev_enumerate_get_list_entry(e);
1185 udev_list_entry_foreach(item, first) {
1186 _cleanup_free_ char *t = NULL;
1189 p = udev_list_entry_get_name(item);
1191 t = strappend(p, "/uevent");
1195 write_string_file(t, "change");
1201 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1202 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1203 _cleanup_free_ char *rule = NULL, *file = NULL;
1204 const char *id_for_seat;
1211 d = udev_device_new_from_syspath(m->udev, sysfs);
1215 if (!udev_device_has_tag(d, "seat"))
1218 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1222 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1225 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1228 mkdir_p_label("/etc/udev/rules.d", 0755);
1229 mac_selinux_init("/etc");
1230 r = write_string_file_atomic_label(file, rule);
1234 return trigger_device(m, d);
1237 static int flush_devices(Manager *m) {
1238 _cleanup_closedir_ DIR *d;
1242 d = opendir("/etc/udev/rules.d");
1244 if (errno != ENOENT)
1245 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1249 while ((de = readdir(d))) {
1251 if (!dirent_is_file(de))
1254 if (!startswith(de->d_name, "72-seat-"))
1257 if (!endswith(de->d_name, ".rules"))
1260 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1261 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1265 return trigger_device(m, NULL);
1268 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1269 const char *sysfs, *seat;
1270 Manager *m = userdata;
1277 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1281 if (!path_startswith(sysfs, "/sys"))
1282 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1284 if (!seat_name_is_valid(seat))
1285 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1287 r = bus_verify_polkit_async(
1290 "org.freedesktop.login1.attach-device",
1293 &m->polkit_registry,
1298 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1300 r = attach_device(m, seat, sysfs);
1304 return sd_bus_reply_method_return(message, NULL);
1307 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1308 Manager *m = userdata;
1315 r = sd_bus_message_read(message, "b", &interactive);
1319 r = bus_verify_polkit_async(
1322 "org.freedesktop.login1.flush-devices",
1325 &m->polkit_registry,
1330 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1332 r = flush_devices(m);
1336 return sd_bus_reply_method_return(message, NULL);
1339 static int have_multiple_sessions(
1348 /* Check for other users' sessions. Greeter sessions do not
1349 * count, and non-login sessions do not count either. */
1350 HASHMAP_FOREACH(session, m->sessions, i)
1351 if (session->class == SESSION_USER &&
1352 session->user->uid != uid)
1358 static int bus_manager_log_shutdown(
1361 const char *unit_name) {
1368 if (w != INHIBIT_SHUTDOWN)
1371 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1372 p = "MESSAGE=System is powering down.";
1373 q = "SHUTDOWN=power-off";
1374 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1375 p = "MESSAGE=System is halting.";
1376 q = "SHUTDOWN=halt";
1377 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1378 p = "MESSAGE=System is rebooting.";
1379 q = "SHUTDOWN=reboot";
1380 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1381 p = "MESSAGE=System is rebooting with kexec.";
1382 q = "SHUTDOWN=kexec";
1384 p = "MESSAGE=System is shutting down.";
1388 return log_struct(LOG_NOTICE,
1389 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1395 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1396 Manager *m = userdata;
1401 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1405 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1410 if (until <= now(CLOCK_MONOTONIC))
1413 /* We want to ignore the lid switch for a while after each
1414 * suspend, and after boot-up. Hence let's install a timer for
1415 * this. As long as the event source exists we ignore the lid
1418 if (m->lid_switch_ignore_event_source) {
1421 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1428 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1430 r = sd_event_add_time(
1432 &m->lid_switch_ignore_event_source,
1435 lid_switch_ignore_handler, m);
1440 static int execute_shutdown_or_sleep(
1443 const char *unit_name,
1444 sd_bus_error *error) {
1446 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1453 assert(w < _INHIBIT_WHAT_MAX);
1456 bus_manager_log_shutdown(m, w, unit_name);
1458 r = sd_bus_call_method(
1460 "org.freedesktop.systemd1",
1461 "/org/freedesktop/systemd1",
1462 "org.freedesktop.systemd1.Manager",
1466 "ss", unit_name, "replace-irreversibly");
1470 r = sd_bus_message_read(reply, "o", &p);
1478 m->action_unit = unit_name;
1479 free(m->action_job);
1483 /* Make sure the lid switch is ignored for a while */
1484 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1489 static int manager_inhibit_timeout_handler(
1494 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1495 Inhibitor *offending = NULL;
1496 Manager *manager = userdata;
1500 assert(manager->inhibit_timeout_source == s);
1502 if (manager->action_what == 0 || manager->action_job)
1505 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1506 _cleanup_free_ char *comm = NULL, *u = NULL;
1508 (void) get_process_comm(offending->pid, &comm);
1509 u = uid_to_name(offending->uid);
1511 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1512 offending->uid, strna(u),
1513 offending->pid, strna(comm));
1516 /* Actually do the operation */
1517 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1519 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1521 manager->action_unit = NULL;
1522 manager->action_what = 0;
1528 static int delay_shutdown_or_sleep(
1531 const char *unit_name) {
1538 assert(w < _INHIBIT_WHAT_MAX);
1541 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1543 if (m->inhibit_timeout_source) {
1544 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1546 return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
1548 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1550 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
1552 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1553 timeout_val, 0, manager_inhibit_timeout_handler, m);
1558 m->action_unit = unit_name;
1564 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1566 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1567 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1568 [INHIBIT_SLEEP] = "PrepareForSleep"
1571 int active = _active;
1575 assert(w < _INHIBIT_WHAT_MAX);
1576 assert(signal_name[w]);
1578 return sd_bus_emit_signal(m->bus,
1579 "/org/freedesktop/login1",
1580 "org.freedesktop.login1.Manager",
1586 int bus_manager_shutdown_or_sleep_now_or_later(
1588 const char *unit_name,
1590 sd_bus_error *error) {
1598 assert(w <= _INHIBIT_WHAT_MAX);
1599 assert(!m->action_job);
1601 /* Tell everybody to prepare for shutdown/sleep */
1602 send_prepare_for(m, w, true);
1605 m->inhibit_delay_max > 0 &&
1606 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1609 /* Shutdown is delayed, keep in mind what we
1610 * want to do, and start a timeout */
1611 r = delay_shutdown_or_sleep(m, w, unit_name);
1613 /* Shutdown is not delayed, execute it
1615 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1620 static int verify_shutdown_creds(
1622 sd_bus_message *message,
1626 const char *action_multiple_sessions,
1627 const char *action_ignore_inhibit,
1628 sd_bus_error *error) {
1630 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1631 bool multiple_sessions, blocked;
1638 assert(w <= _INHIBIT_WHAT_MAX);
1640 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1644 r = sd_bus_creds_get_euid(creds, &uid);
1648 r = have_multiple_sessions(m, uid);
1652 multiple_sessions = r > 0;
1653 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1655 if (multiple_sessions && action_multiple_sessions) {
1656 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1660 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1663 if (blocked && action_ignore_inhibit) {
1664 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1668 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1671 if (!multiple_sessions && !blocked && action) {
1672 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1676 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1682 static int method_do_shutdown_or_sleep(
1684 sd_bus_message *message,
1685 const char *unit_name,
1688 const char *action_multiple_sessions,
1689 const char *action_ignore_inhibit,
1690 const char *sleep_verb,
1691 sd_bus_error *error) {
1699 assert(w <= _INHIBIT_WHAT_MAX);
1701 r = sd_bus_message_read(message, "b", &interactive);
1705 /* Don't allow multiple jobs being executed at the same time */
1707 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1710 r = can_sleep(sleep_verb);
1715 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1718 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1719 action_ignore_inhibit, error);
1723 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1727 return sd_bus_reply_method_return(message, NULL);
1730 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1731 Manager *m = userdata;
1733 return method_do_shutdown_or_sleep(
1735 SPECIAL_POWEROFF_TARGET,
1737 "org.freedesktop.login1.power-off",
1738 "org.freedesktop.login1.power-off-multiple-sessions",
1739 "org.freedesktop.login1.power-off-ignore-inhibit",
1744 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1745 Manager *m = userdata;
1747 return method_do_shutdown_or_sleep(
1749 SPECIAL_REBOOT_TARGET,
1751 "org.freedesktop.login1.reboot",
1752 "org.freedesktop.login1.reboot-multiple-sessions",
1753 "org.freedesktop.login1.reboot-ignore-inhibit",
1758 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1759 Manager *m = userdata;
1761 return method_do_shutdown_or_sleep(
1763 SPECIAL_SUSPEND_TARGET,
1765 "org.freedesktop.login1.suspend",
1766 "org.freedesktop.login1.suspend-multiple-sessions",
1767 "org.freedesktop.login1.suspend-ignore-inhibit",
1772 static int manager_scheduled_shutdown_handler(
1777 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1778 Manager *m = userdata;
1784 if (isempty(m->scheduled_shutdown_type))
1787 if (streq(m->scheduled_shutdown_type, "halt"))
1788 target = SPECIAL_HALT_TARGET;
1789 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1790 target = SPECIAL_POWEROFF_TARGET;
1792 target = SPECIAL_REBOOT_TARGET;
1794 r = execute_shutdown_or_sleep(m, 0, target, &error);
1796 return log_error_errno(r, "Unable to execute transition to %s: %m\n", target);
1801 static int method_schedule_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1802 Manager *m = userdata;
1803 const char *action_multiple_sessions = NULL;
1804 const char *action_ignore_inhibit = NULL;
1805 const char *action = NULL;
1813 r = sd_bus_message_read(message, "st", &type, &elapse);
1817 if (streq(type, "reboot")) {
1818 action = "org.freedesktop.login1.reboot";
1819 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1820 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1821 } else if (streq(type, "halt")) {
1822 action = "org.freedesktop.login1.halt";
1823 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1824 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1825 } else if (streq(type, "poweroff")) {
1826 action = "org.freedesktop.login1.poweroff";
1827 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1828 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1830 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1832 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1833 action, action_multiple_sessions, action_ignore_inhibit, error);
1837 if (m->scheduled_shutdown_timeout_source) {
1838 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1840 return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
1842 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
1844 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
1846 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
1847 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
1849 return log_error_errno(r, "sd_event_add_time() failed: %m\n");
1852 r = free_and_strdup(&m->scheduled_shutdown_type, type);
1854 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1858 m->scheduled_shutdown_timeout = elapse;
1860 return sd_bus_reply_method_return(message, NULL);
1863 static int method_cancel_scheduled_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1864 Manager *m = userdata;
1870 cancelled = m->scheduled_shutdown_type != NULL;
1872 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1873 free(m->scheduled_shutdown_type);
1874 m->scheduled_shutdown_type = NULL;
1875 m->scheduled_shutdown_timeout = 0;
1877 return sd_bus_reply_method_return(message, "b", cancelled);
1880 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1881 Manager *m = userdata;
1883 return method_do_shutdown_or_sleep(
1885 SPECIAL_HIBERNATE_TARGET,
1887 "org.freedesktop.login1.hibernate",
1888 "org.freedesktop.login1.hibernate-multiple-sessions",
1889 "org.freedesktop.login1.hibernate-ignore-inhibit",
1894 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1895 Manager *m = userdata;
1897 return method_do_shutdown_or_sleep(
1899 SPECIAL_HYBRID_SLEEP_TARGET,
1901 "org.freedesktop.login1.hibernate",
1902 "org.freedesktop.login1.hibernate-multiple-sessions",
1903 "org.freedesktop.login1.hibernate-ignore-inhibit",
1908 static int method_can_shutdown_or_sleep(
1910 sd_bus_message *message,
1913 const char *action_multiple_sessions,
1914 const char *action_ignore_inhibit,
1915 const char *sleep_verb,
1916 sd_bus_error *error) {
1918 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1919 bool multiple_sessions, challenge, blocked;
1920 const char *result = NULL;
1927 assert(w <= _INHIBIT_WHAT_MAX);
1929 assert(action_multiple_sessions);
1930 assert(action_ignore_inhibit);
1933 r = can_sleep(sleep_verb);
1937 return sd_bus_reply_method_return(message, "s", "na");
1940 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1944 r = sd_bus_creds_get_euid(creds, &uid);
1948 r = have_multiple_sessions(m, uid);
1952 multiple_sessions = r > 0;
1953 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1955 if (multiple_sessions) {
1956 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
1963 result = "challenge";
1969 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
1973 if (r > 0 && !result)
1975 else if (challenge && (!result || streq(result, "yes")))
1976 result = "challenge";
1981 if (!multiple_sessions && !blocked) {
1982 /* If neither inhibit nor multiple sessions
1983 * apply then just check the normal policy */
1985 r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
1992 result = "challenge";
1997 return sd_bus_reply_method_return(message, "s", result);
2000 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2001 Manager *m = userdata;
2003 return method_can_shutdown_or_sleep(
2006 "org.freedesktop.login1.power-off",
2007 "org.freedesktop.login1.power-off-multiple-sessions",
2008 "org.freedesktop.login1.power-off-ignore-inhibit",
2013 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2014 Manager *m = userdata;
2016 return method_can_shutdown_or_sleep(
2019 "org.freedesktop.login1.reboot",
2020 "org.freedesktop.login1.reboot-multiple-sessions",
2021 "org.freedesktop.login1.reboot-ignore-inhibit",
2026 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2027 Manager *m = userdata;
2029 return method_can_shutdown_or_sleep(
2032 "org.freedesktop.login1.suspend",
2033 "org.freedesktop.login1.suspend-multiple-sessions",
2034 "org.freedesktop.login1.suspend-ignore-inhibit",
2039 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2040 Manager *m = userdata;
2042 return method_can_shutdown_or_sleep(
2045 "org.freedesktop.login1.hibernate",
2046 "org.freedesktop.login1.hibernate-multiple-sessions",
2047 "org.freedesktop.login1.hibernate-ignore-inhibit",
2052 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2053 Manager *m = userdata;
2055 return method_can_shutdown_or_sleep(
2058 "org.freedesktop.login1.hibernate",
2059 "org.freedesktop.login1.hibernate-multiple-sessions",
2060 "org.freedesktop.login1.hibernate-ignore-inhibit",
2065 static int property_get_reboot_to_firmware_setup(
2068 const char *interface,
2069 const char *property,
2070 sd_bus_message *reply,
2072 sd_bus_error *error) {
2079 r = efi_get_reboot_to_firmware();
2080 if (r < 0 && r != -EOPNOTSUPP)
2083 return sd_bus_message_append(reply, "b", r > 0);
2086 static int method_set_reboot_to_firmware_setup(
2088 sd_bus_message *message,
2090 sd_bus_error *error) {
2093 Manager *m = userdata;
2099 r = sd_bus_message_read(message, "b", &b);
2103 r = bus_verify_polkit_async(message,
2105 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2108 &m->polkit_registry,
2113 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2115 r = efi_set_reboot_to_firmware(b);
2119 return sd_bus_reply_method_return(message, NULL);
2122 static int method_can_reboot_to_firmware_setup(
2124 sd_bus_message *message,
2126 sd_bus_error *error) {
2131 Manager *m = userdata;
2137 r = efi_reboot_to_firmware_supported();
2138 if (r == -EOPNOTSUPP)
2139 return sd_bus_reply_method_return(message, "s", "na");
2143 r = bus_test_polkit(message,
2145 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2155 result = "challenge";
2159 return sd_bus_reply_method_return(message, "s", result);
2162 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2163 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2164 const char *who, *why, *what, *mode;
2165 _cleanup_free_ char *id = NULL;
2166 _cleanup_close_ int fifo_fd = -1;
2167 Manager *m = userdata;
2168 Inhibitor *i = NULL;
2179 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2183 w = inhibit_what_from_string(what);
2185 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2187 mm = inhibit_mode_from_string(mode);
2189 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2191 /* Delay is only supported for shutdown/sleep */
2192 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2193 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2195 /* Don't allow taking delay locks while we are already
2196 * executing the operation. We shouldn't create the impression
2197 * that the lock was successful if the machine is about to go
2198 * down/suspend any moment. */
2199 if (m->action_what & w)
2200 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2202 r = bus_verify_polkit_async(
2205 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2206 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2207 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2208 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2209 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2210 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2211 "org.freedesktop.login1.inhibit-handle-lid-switch",
2214 &m->polkit_registry,
2219 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2221 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2225 r = sd_bus_creds_get_euid(creds, &uid);
2229 r = sd_bus_creds_get_pid(creds, &pid);
2237 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2240 } while (hashmap_get(m->inhibitors, id));
2242 r = manager_add_inhibitor(m, id, &i);
2250 i->why = strdup(why);
2251 i->who = strdup(who);
2253 if (!i->why || !i->who) {
2258 fifo_fd = inhibitor_create_fifo(i);
2266 return sd_bus_reply_method_return(message, "h", fifo_fd);
2275 const sd_bus_vtable manager_vtable[] = {
2276 SD_BUS_VTABLE_START(0),
2278 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2279 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2280 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2281 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2282 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2283 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2284 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2285 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2286 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2287 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2288 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2289 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2290 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2291 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2292 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2293 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2294 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2295 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2296 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2297 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2298 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2299 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2301 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2302 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2303 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2304 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2305 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2306 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2307 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2308 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2309 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2310 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2311 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2312 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2313 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2314 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2315 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2316 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2317 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2318 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2319 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2320 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2321 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2322 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2323 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2324 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2325 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2326 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2327 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2328 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2329 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2330 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2331 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2332 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2333 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2334 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2335 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2336 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2337 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2338 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2339 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2340 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2342 SD_BUS_SIGNAL("SessionNew", "so", 0),
2343 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2344 SD_BUS_SIGNAL("UserNew", "uo", 0),
2345 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2346 SD_BUS_SIGNAL("SeatNew", "so", 0),
2347 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2348 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2349 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2354 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2363 if (streq(result, "done"))
2364 r = session_send_create_reply(s, NULL);
2366 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2368 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2369 r = session_send_create_reply(s, &e);
2375 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2376 const char *path, *result, *unit;
2377 Manager *m = userdata;
2387 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2389 bus_log_parse_error(r);
2393 if (m->action_job && streq(m->action_job, path)) {
2394 log_info("Operation finished.");
2396 /* Tell people that they now may take a lock again */
2397 send_prepare_for(m, m->action_what, false);
2399 free(m->action_job);
2400 m->action_job = NULL;
2401 m->action_unit = NULL;
2406 session = hashmap_get(m->session_units, unit);
2409 if (streq_ptr(path, session->scope_job)) {
2410 free(session->scope_job);
2411 session->scope_job = NULL;
2414 session_jobs_reply(session, unit, result);
2416 session_save(session);
2417 session_add_to_gc_queue(session);
2420 user = hashmap_get(m->user_units, unit);
2423 if (streq_ptr(path, user->service_job)) {
2424 free(user->service_job);
2425 user->service_job = NULL;
2428 if (streq_ptr(path, user->slice_job)) {
2429 free(user->slice_job);
2430 user->slice_job = NULL;
2433 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2434 session_jobs_reply(session, unit, result);
2438 user_add_to_gc_queue(user);
2444 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2445 const char *path, *unit;
2446 Manager *m = userdata;
2455 r = sd_bus_message_read(message, "so", &unit, &path);
2457 bus_log_parse_error(r);
2461 session = hashmap_get(m->session_units, unit);
2463 session_add_to_gc_queue(session);
2465 user = hashmap_get(m->user_units, unit);
2467 user_add_to_gc_queue(user);
2472 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2473 _cleanup_free_ char *unit = NULL;
2474 Manager *m = userdata;
2484 path = sd_bus_message_get_path(message);
2488 r = unit_name_from_dbus_path(path, &unit);
2489 if (r == -EINVAL) /* not a unit */
2494 session = hashmap_get(m->session_units, unit);
2496 session_add_to_gc_queue(session);
2498 user = hashmap_get(m->user_units, unit);
2500 user_add_to_gc_queue(user);
2505 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2506 Manager *m = userdata;
2513 r = sd_bus_message_read(message, "b", &b);
2515 bus_log_parse_error(r);
2522 /* systemd finished reloading, let's recheck all our sessions */
2523 log_debug("System manager has been reloaded, rechecking sessions...");
2525 HASHMAP_FOREACH(session, m->sessions, i)
2526 session_add_to_gc_queue(session);
2531 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2532 const char *name, *old, *new;
2533 Manager *m = userdata;
2541 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2543 bus_log_parse_error(r);
2547 if (isempty(old) || !isempty(new))
2550 key = set_remove(m->busnames, (char*) old);
2554 /* Drop all controllers owned by this name */
2558 HASHMAP_FOREACH(session, m->sessions, i)
2559 if (session_is_controller(session, old))
2560 session_drop_controller(session);
2565 int manager_send_changed(Manager *manager, const char *property, ...) {
2570 l = strv_from_stdarg_alloca(property);
2572 return sd_bus_emit_properties_changed_strv(
2574 "/org/freedesktop/login1",
2575 "org.freedesktop.login1.Manager",
2579 int manager_start_scope(
2584 const char *description,
2585 const char *after, const char *after2,
2586 sd_bus_error *error,
2589 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2596 r = sd_bus_message_new_method_call(
2599 "org.freedesktop.systemd1",
2600 "/org/freedesktop/systemd1",
2601 "org.freedesktop.systemd1.Manager",
2602 "StartTransientUnit");
2606 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2610 r = sd_bus_message_open_container(m, 'a', "(sv)");
2614 if (!isempty(slice)) {
2615 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2620 if (!isempty(description)) {
2621 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2626 if (!isempty(after)) {
2627 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2632 if (!isempty(after2)) {
2633 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2638 /* cgroup empty notification is not available in containers
2639 * currently. To make this less problematic, let's shorten the
2640 * stop timeout for sessions, so that we don't wait
2643 /* Make sure that the session shells are terminated with
2644 * SIGHUP since bash and friends tend to ignore SIGTERM */
2645 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2649 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2653 r = sd_bus_message_close_container(m);
2657 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2661 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2669 r = sd_bus_message_read(reply, "o", &j);
2683 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2684 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2690 r = sd_bus_call_method(
2692 "org.freedesktop.systemd1",
2693 "/org/freedesktop/systemd1",
2694 "org.freedesktop.systemd1.Manager",
2698 "ss", unit, "fail");
2706 r = sd_bus_message_read(reply, "o", &j);
2720 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2721 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2727 r = sd_bus_call_method(
2729 "org.freedesktop.systemd1",
2730 "/org/freedesktop/systemd1",
2731 "org.freedesktop.systemd1.Manager",
2735 "ss", unit, "fail");
2737 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2738 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2743 sd_bus_error_free(error);
2754 r = sd_bus_message_read(reply, "o", &j);
2768 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2769 _cleanup_free_ char *path = NULL;
2775 path = unit_dbus_path_from_name(scope);
2779 r = sd_bus_call_method(
2781 "org.freedesktop.systemd1",
2783 "org.freedesktop.systemd1.Scope",
2789 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2790 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2791 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2792 sd_bus_error_free(error);
2802 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2806 return sd_bus_call_method(
2808 "org.freedesktop.systemd1",
2809 "/org/freedesktop/systemd1",
2810 "org.freedesktop.systemd1.Manager",
2814 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2817 int manager_unit_is_active(Manager *manager, const char *unit) {
2818 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2819 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2820 _cleanup_free_ char *path = NULL;
2827 path = unit_dbus_path_from_name(unit);
2831 r = sd_bus_get_property(
2833 "org.freedesktop.systemd1",
2835 "org.freedesktop.systemd1.Unit",
2841 /* systemd might have droppped off momentarily, let's
2842 * not make this an error */
2843 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2844 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2847 /* If the unit is already unloaded then it's not
2849 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2850 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2856 r = sd_bus_message_read(reply, "s", &state);
2860 return !streq(state, "inactive") && !streq(state, "failed");
2863 int manager_job_is_active(Manager *manager, const char *path) {
2864 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2865 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2871 r = sd_bus_get_property(
2873 "org.freedesktop.systemd1",
2875 "org.freedesktop.systemd1.Job",
2881 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2882 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2885 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2891 /* We don't actually care about the state really. The fact
2892 * that we could read the job state is enough for us */