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/>.
28 #include "sd-messages.h"
31 #include "path-util.h"
33 #include "sleep-config.h"
34 #include "fileio-label.h"
37 #include "unit-name.h"
41 #include "bus-error.h"
42 #include "bus-common-errors.h"
43 #include "udev-util.h"
44 #include "selinux-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 session_release(session);
836 return sd_bus_reply_method_return(message, NULL);
839 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
840 Manager *m = userdata;
849 r = sd_bus_message_read(message, "s", &name);
853 r = manager_get_session_from_creds(m, message, name, error, &session);
857 return bus_session_method_activate(bus, message, session, error);
860 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
861 const char *session_name, *seat_name;
862 Manager *m = userdata;
871 /* Same as ActivateSession() but refuses to work if
872 * the seat doesn't match */
874 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
878 r = manager_get_session_from_creds(m, message, session_name, error, &session);
882 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
886 if (session->seat != seat)
887 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
889 r = session_activate(session);
893 return sd_bus_reply_method_return(message, NULL);
896 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
897 Manager *m = userdata;
906 r = sd_bus_message_read(message, "s", &name);
910 r = manager_get_session_from_creds(m, message, name, error, &session);
914 return bus_session_method_lock(bus, message, session, error);
917 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
918 Manager *m = userdata;
925 r = bus_verify_polkit_async(
928 "org.freedesktop.login1.lock-sessions",
936 return 1; /* Will call us back */
938 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
942 return sd_bus_reply_method_return(message, NULL);
945 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
947 Manager *m = userdata;
955 r = sd_bus_message_read(message, "s", &name);
959 r = manager_get_session_from_creds(m, message, name, error, &session);
963 return bus_session_method_kill(bus, message, session, error);
966 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
967 Manager *m = userdata;
976 r = sd_bus_message_read(message, "u", &uid);
980 r = manager_get_user_from_creds(m, message, uid, error, &user);
984 return bus_user_method_kill(bus, message, user, error);
987 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
988 Manager *m = userdata;
997 r = sd_bus_message_read(message, "s", &name);
1001 r = manager_get_session_from_creds(m, message, name, error, &session);
1005 return bus_session_method_terminate(bus, message, session, error);
1008 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1009 Manager *m = userdata;
1018 r = sd_bus_message_read(message, "u", &uid);
1022 r = manager_get_user_from_creds(m, message, uid, error, &user);
1026 return bus_user_method_terminate(bus, message, user, error);
1029 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1030 Manager *m = userdata;
1039 r = sd_bus_message_read(message, "s", &name);
1043 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1047 return bus_seat_method_terminate(bus, message, seat, error);
1050 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1051 _cleanup_free_ char *cc = NULL;
1052 Manager *m = userdata;
1063 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1067 if (uid == UID_INVALID) {
1068 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1070 /* Note that we get the owner UID of the session, not the actual client UID here! */
1071 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1075 r = sd_bus_creds_get_owner_uid(creds, &uid);
1083 return errno ? -errno : -ENOENT;
1085 r = bus_verify_polkit_async(
1088 "org.freedesktop.login1.set-user-linger",
1091 &m->polkit_registry,
1096 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1098 mkdir_p_label("/var/lib/systemd", 0755);
1100 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1104 cc = cescape(pw->pw_name);
1108 path = strjoina("/var/lib/systemd/linger/", cc);
1116 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1123 if (r < 0 && errno != ENOENT)
1126 u = hashmap_get(m->users, UID_TO_PTR(uid));
1128 user_add_to_gc_queue(u);
1131 return sd_bus_reply_method_return(message, NULL);
1134 static int trigger_device(Manager *m, struct udev_device *d) {
1135 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1136 struct udev_list_entry *first, *item;
1141 e = udev_enumerate_new(m->udev);
1146 r = udev_enumerate_add_match_parent(e, d);
1151 r = udev_enumerate_scan_devices(e);
1155 first = udev_enumerate_get_list_entry(e);
1156 udev_list_entry_foreach(item, first) {
1157 _cleanup_free_ char *t = NULL;
1160 p = udev_list_entry_get_name(item);
1162 t = strappend(p, "/uevent");
1166 write_string_file(t, "change");
1172 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1173 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1174 _cleanup_free_ char *rule = NULL, *file = NULL;
1175 const char *id_for_seat;
1182 d = udev_device_new_from_syspath(m->udev, sysfs);
1186 if (!udev_device_has_tag(d, "seat"))
1189 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1193 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1196 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1199 mkdir_p_label("/etc/udev/rules.d", 0755);
1200 mac_selinux_init("/etc");
1201 r = write_string_file_atomic_label(file, rule);
1205 return trigger_device(m, d);
1208 static int flush_devices(Manager *m) {
1209 _cleanup_closedir_ DIR *d;
1213 d = opendir("/etc/udev/rules.d");
1215 if (errno != ENOENT)
1216 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1220 while ((de = readdir(d))) {
1222 if (!dirent_is_file(de))
1225 if (!startswith(de->d_name, "72-seat-"))
1228 if (!endswith(de->d_name, ".rules"))
1231 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1232 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1236 return trigger_device(m, NULL);
1239 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1240 const char *sysfs, *seat;
1241 Manager *m = userdata;
1248 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1252 if (!path_startswith(sysfs, "/sys"))
1253 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1255 if (!seat_name_is_valid(seat))
1256 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1258 r = bus_verify_polkit_async(
1261 "org.freedesktop.login1.attach-device",
1264 &m->polkit_registry,
1269 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1271 r = attach_device(m, seat, sysfs);
1275 return sd_bus_reply_method_return(message, NULL);
1278 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1279 Manager *m = userdata;
1286 r = sd_bus_message_read(message, "b", &interactive);
1290 r = bus_verify_polkit_async(
1293 "org.freedesktop.login1.flush-devices",
1296 &m->polkit_registry,
1301 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1303 r = flush_devices(m);
1307 return sd_bus_reply_method_return(message, NULL);
1310 static int have_multiple_sessions(
1319 /* Check for other users' sessions. Greeter sessions do not
1320 * count, and non-login sessions do not count either. */
1321 HASHMAP_FOREACH(session, m->sessions, i)
1322 if (session->class == SESSION_USER &&
1323 session->user->uid != uid)
1329 static int bus_manager_log_shutdown(
1332 const char *unit_name) {
1339 if (w != INHIBIT_SHUTDOWN)
1342 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1343 p = "MESSAGE=System is powering down.";
1344 q = "SHUTDOWN=power-off";
1345 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1346 p = "MESSAGE=System is halting.";
1347 q = "SHUTDOWN=halt";
1348 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1349 p = "MESSAGE=System is rebooting.";
1350 q = "SHUTDOWN=reboot";
1351 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1352 p = "MESSAGE=System is rebooting with kexec.";
1353 q = "SHUTDOWN=kexec";
1355 p = "MESSAGE=System is shutting down.";
1359 return log_struct(LOG_NOTICE,
1360 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1366 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1367 Manager *m = userdata;
1372 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1376 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1381 if (until <= now(CLOCK_MONOTONIC))
1384 /* We want to ignore the lid switch for a while after each
1385 * suspend, and after boot-up. Hence let's install a timer for
1386 * this. As long as the event source exists we ignore the lid
1389 if (m->lid_switch_ignore_event_source) {
1392 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1399 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1401 r = sd_event_add_time(
1403 &m->lid_switch_ignore_event_source,
1406 lid_switch_ignore_handler, m);
1411 static int execute_shutdown_or_sleep(
1414 const char *unit_name,
1415 sd_bus_error *error) {
1417 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1424 assert(w < _INHIBIT_WHAT_MAX);
1427 bus_manager_log_shutdown(m, w, unit_name);
1429 r = sd_bus_call_method(
1431 "org.freedesktop.systemd1",
1432 "/org/freedesktop/systemd1",
1433 "org.freedesktop.systemd1.Manager",
1437 "ss", unit_name, "replace-irreversibly");
1441 r = sd_bus_message_read(reply, "o", &p);
1449 m->action_unit = unit_name;
1450 free(m->action_job);
1454 /* Make sure the lid switch is ignored for a while */
1455 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + IGNORE_LID_SWITCH_SUSPEND_USEC);
1460 static int delay_shutdown_or_sleep(
1463 const char *unit_name) {
1467 assert(w < _INHIBIT_WHAT_MAX);
1470 m->action_timestamp = now(CLOCK_MONOTONIC);
1471 m->action_unit = unit_name;
1477 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1479 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1480 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1481 [INHIBIT_SLEEP] = "PrepareForSleep"
1484 int active = _active;
1488 assert(w < _INHIBIT_WHAT_MAX);
1489 assert(signal_name[w]);
1491 return sd_bus_emit_signal(m->bus,
1492 "/org/freedesktop/login1",
1493 "org.freedesktop.login1.Manager",
1499 int bus_manager_shutdown_or_sleep_now_or_later(
1501 const char *unit_name,
1503 sd_bus_error *error) {
1511 assert(w <= _INHIBIT_WHAT_MAX);
1512 assert(!m->action_job);
1514 /* Tell everybody to prepare for shutdown/sleep */
1515 send_prepare_for(m, w, true);
1518 m->inhibit_delay_max > 0 &&
1519 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1522 /* Shutdown is delayed, keep in mind what we
1523 * want to do, and start a timeout */
1524 r = delay_shutdown_or_sleep(m, w, unit_name);
1526 /* Shutdown is not delayed, execute it
1528 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1533 static int method_do_shutdown_or_sleep(
1535 sd_bus_message *message,
1536 const char *unit_name,
1539 const char *action_multiple_sessions,
1540 const char *action_ignore_inhibit,
1541 const char *sleep_verb,
1542 sd_bus_message_handler_t method,
1543 sd_bus_error *error) {
1545 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1546 bool multiple_sessions, blocked;
1554 assert(w <= _INHIBIT_WHAT_MAX);
1556 assert(action_multiple_sessions);
1557 assert(action_ignore_inhibit);
1560 r = sd_bus_message_read(message, "b", &interactive);
1564 /* Don't allow multiple jobs being executed at the same time */
1566 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1569 r = can_sleep(sleep_verb);
1574 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1577 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1581 r = sd_bus_creds_get_euid(creds, &uid);
1585 r = have_multiple_sessions(m, uid);
1589 multiple_sessions = r > 0;
1590 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1592 if (multiple_sessions) {
1593 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1597 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1601 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1605 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1608 if (!multiple_sessions && !blocked) {
1609 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1613 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1616 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1620 return sd_bus_reply_method_return(message, NULL);
1623 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1624 Manager *m = userdata;
1626 return method_do_shutdown_or_sleep(
1628 SPECIAL_POWEROFF_TARGET,
1630 "org.freedesktop.login1.power-off",
1631 "org.freedesktop.login1.power-off-multiple-sessions",
1632 "org.freedesktop.login1.power-off-ignore-inhibit",
1638 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1639 Manager *m = userdata;
1641 return method_do_shutdown_or_sleep(
1643 SPECIAL_REBOOT_TARGET,
1645 "org.freedesktop.login1.reboot",
1646 "org.freedesktop.login1.reboot-multiple-sessions",
1647 "org.freedesktop.login1.reboot-ignore-inhibit",
1653 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1654 Manager *m = userdata;
1656 return method_do_shutdown_or_sleep(
1658 SPECIAL_SUSPEND_TARGET,
1660 "org.freedesktop.login1.suspend",
1661 "org.freedesktop.login1.suspend-multiple-sessions",
1662 "org.freedesktop.login1.suspend-ignore-inhibit",
1668 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1669 Manager *m = userdata;
1671 return method_do_shutdown_or_sleep(
1673 SPECIAL_HIBERNATE_TARGET,
1675 "org.freedesktop.login1.hibernate",
1676 "org.freedesktop.login1.hibernate-multiple-sessions",
1677 "org.freedesktop.login1.hibernate-ignore-inhibit",
1683 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1684 Manager *m = userdata;
1686 return method_do_shutdown_or_sleep(
1688 SPECIAL_HYBRID_SLEEP_TARGET,
1690 "org.freedesktop.login1.hibernate",
1691 "org.freedesktop.login1.hibernate-multiple-sessions",
1692 "org.freedesktop.login1.hibernate-ignore-inhibit",
1694 method_hybrid_sleep,
1698 static int method_can_shutdown_or_sleep(
1700 sd_bus_message *message,
1703 const char *action_multiple_sessions,
1704 const char *action_ignore_inhibit,
1705 const char *sleep_verb,
1706 sd_bus_error *error) {
1708 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1709 bool multiple_sessions, challenge, blocked;
1710 const char *result = NULL;
1717 assert(w <= _INHIBIT_WHAT_MAX);
1719 assert(action_multiple_sessions);
1720 assert(action_ignore_inhibit);
1723 r = can_sleep(sleep_verb);
1727 return sd_bus_reply_method_return(message, "s", "na");
1730 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1734 r = sd_bus_creds_get_euid(creds, &uid);
1738 r = have_multiple_sessions(m, uid);
1742 multiple_sessions = r > 0;
1743 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1745 if (multiple_sessions) {
1746 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, UID_INVALID, &challenge, error);
1753 result = "challenge";
1759 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, UID_INVALID, &challenge, error);
1763 if (r > 0 && !result)
1765 else if (challenge && (!result || streq(result, "yes")))
1766 result = "challenge";
1771 if (!multiple_sessions && !blocked) {
1772 /* If neither inhibit nor multiple sessions
1773 * apply then just check the normal policy */
1775 r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, UID_INVALID, &challenge, error);
1782 result = "challenge";
1787 return sd_bus_reply_method_return(message, "s", result);
1790 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1791 Manager *m = userdata;
1793 return method_can_shutdown_or_sleep(
1796 "org.freedesktop.login1.power-off",
1797 "org.freedesktop.login1.power-off-multiple-sessions",
1798 "org.freedesktop.login1.power-off-ignore-inhibit",
1803 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1804 Manager *m = userdata;
1806 return method_can_shutdown_or_sleep(
1809 "org.freedesktop.login1.reboot",
1810 "org.freedesktop.login1.reboot-multiple-sessions",
1811 "org.freedesktop.login1.reboot-ignore-inhibit",
1816 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1817 Manager *m = userdata;
1819 return method_can_shutdown_or_sleep(
1822 "org.freedesktop.login1.suspend",
1823 "org.freedesktop.login1.suspend-multiple-sessions",
1824 "org.freedesktop.login1.suspend-ignore-inhibit",
1829 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1830 Manager *m = userdata;
1832 return method_can_shutdown_or_sleep(
1835 "org.freedesktop.login1.hibernate",
1836 "org.freedesktop.login1.hibernate-multiple-sessions",
1837 "org.freedesktop.login1.hibernate-ignore-inhibit",
1842 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1843 Manager *m = userdata;
1845 return method_can_shutdown_or_sleep(
1848 "org.freedesktop.login1.hibernate",
1849 "org.freedesktop.login1.hibernate-multiple-sessions",
1850 "org.freedesktop.login1.hibernate-ignore-inhibit",
1855 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1856 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1857 const char *who, *why, *what, *mode;
1858 _cleanup_free_ char *id = NULL;
1859 _cleanup_close_ int fifo_fd = -1;
1860 Manager *m = userdata;
1861 Inhibitor *i = NULL;
1872 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1876 w = inhibit_what_from_string(what);
1878 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1880 mm = inhibit_mode_from_string(mode);
1882 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1884 /* Delay is only supported for shutdown/sleep */
1885 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1886 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1888 /* Don't allow taking delay locks while we are already
1889 * executing the operation. We shouldn't create the impression
1890 * that the lock was successful if the machine is about to go
1891 * down/suspend any moment. */
1892 if (m->action_what & w)
1893 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1895 r = bus_verify_polkit_async(
1898 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1899 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1900 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1901 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1902 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1903 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1904 "org.freedesktop.login1.inhibit-handle-lid-switch",
1907 &m->polkit_registry,
1912 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1914 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
1918 r = sd_bus_creds_get_euid(creds, &uid);
1922 r = sd_bus_creds_get_pid(creds, &pid);
1930 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1933 } while (hashmap_get(m->inhibitors, id));
1935 r = manager_add_inhibitor(m, id, &i);
1943 i->why = strdup(why);
1944 i->who = strdup(who);
1946 if (!i->why || !i->who) {
1951 fifo_fd = inhibitor_create_fifo(i);
1959 return sd_bus_reply_method_return(message, "h", fifo_fd);
1968 const sd_bus_vtable manager_vtable[] = {
1969 SD_BUS_VTABLE_START(0),
1971 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
1972 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
1973 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
1974 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
1975 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1976 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1977 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1978 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1979 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1980 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
1981 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
1982 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
1983 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
1984 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
1985 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
1986 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
1987 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1988 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1989 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1991 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
1992 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1993 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
1994 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1995 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1996 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
1997 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
1998 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
1999 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2000 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2001 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2002 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2003 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2006 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2007 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2008 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2009 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2010 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2011 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2012 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2013 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2014 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2015 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2016 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2017 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2018 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2019 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2020 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2021 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2022 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2023 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2024 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2026 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2028 SD_BUS_SIGNAL("SessionNew", "so", 0),
2029 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2030 SD_BUS_SIGNAL("UserNew", "uo", 0),
2031 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2032 SD_BUS_SIGNAL("SeatNew", "so", 0),
2033 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2034 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2035 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2040 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2049 if (streq(result, "done"))
2050 r = session_send_create_reply(s, NULL);
2052 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2054 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2055 r = session_send_create_reply(s, &e);
2061 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2062 const char *path, *result, *unit;
2063 Manager *m = userdata;
2073 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2075 bus_log_parse_error(r);
2079 if (m->action_job && streq(m->action_job, path)) {
2080 log_info("Operation finished.");
2082 /* Tell people that they now may take a lock again */
2083 send_prepare_for(m, m->action_what, false);
2085 free(m->action_job);
2086 m->action_job = NULL;
2087 m->action_unit = NULL;
2092 session = hashmap_get(m->session_units, unit);
2095 if (streq_ptr(path, session->scope_job)) {
2096 free(session->scope_job);
2097 session->scope_job = NULL;
2100 session_jobs_reply(session, unit, result);
2102 session_save(session);
2103 session_add_to_gc_queue(session);
2106 user = hashmap_get(m->user_units, unit);
2109 if (streq_ptr(path, user->service_job)) {
2110 free(user->service_job);
2111 user->service_job = NULL;
2114 if (streq_ptr(path, user->slice_job)) {
2115 free(user->slice_job);
2116 user->slice_job = NULL;
2119 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2120 session_jobs_reply(session, unit, result);
2124 user_add_to_gc_queue(user);
2130 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2131 const char *path, *unit;
2132 Manager *m = userdata;
2141 r = sd_bus_message_read(message, "so", &unit, &path);
2143 bus_log_parse_error(r);
2147 session = hashmap_get(m->session_units, unit);
2149 session_add_to_gc_queue(session);
2151 user = hashmap_get(m->user_units, unit);
2153 user_add_to_gc_queue(user);
2158 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2159 _cleanup_free_ char *unit = NULL;
2160 Manager *m = userdata;
2170 path = sd_bus_message_get_path(message);
2174 r = unit_name_from_dbus_path(path, &unit);
2175 if (r == -EINVAL) /* not a unit */
2180 session = hashmap_get(m->session_units, unit);
2182 session_add_to_gc_queue(session);
2184 user = hashmap_get(m->user_units, unit);
2186 user_add_to_gc_queue(user);
2191 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2192 Manager *m = userdata;
2199 r = sd_bus_message_read(message, "b", &b);
2201 bus_log_parse_error(r);
2208 /* systemd finished reloading, let's recheck all our sessions */
2209 log_debug("System manager has been reloaded, rechecking sessions...");
2211 HASHMAP_FOREACH(session, m->sessions, i)
2212 session_add_to_gc_queue(session);
2217 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2218 const char *name, *old, *new;
2219 Manager *m = userdata;
2227 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2229 bus_log_parse_error(r);
2233 if (isempty(old) || !isempty(new))
2236 key = set_remove(m->busnames, (char*) old);
2240 /* Drop all controllers owned by this name */
2244 HASHMAP_FOREACH(session, m->sessions, i)
2245 if (session_is_controller(session, old))
2246 session_drop_controller(session);
2251 int manager_send_changed(Manager *manager, const char *property, ...) {
2256 l = strv_from_stdarg_alloca(property);
2258 return sd_bus_emit_properties_changed_strv(
2260 "/org/freedesktop/login1",
2261 "org.freedesktop.login1.Manager",
2265 int manager_dispatch_delayed(Manager *manager) {
2266 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2267 Inhibitor *offending = NULL;
2272 if (manager->action_what == 0 || manager->action_job)
2275 /* Continue delay? */
2276 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
2277 _cleanup_free_ char *comm = NULL, *u = NULL;
2279 get_process_comm(offending->pid, &comm);
2280 u = uid_to_name(offending->uid);
2282 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2285 log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
2286 offending->uid, strna(u),
2287 offending->pid, strna(comm));
2290 /* Actually do the operation */
2291 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
2293 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2295 manager->action_unit = NULL;
2296 manager->action_what = 0;
2303 int manager_start_scope(
2308 const char *description,
2309 const char *after, const char *after2,
2310 sd_bus_error *error,
2313 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2320 r = sd_bus_message_new_method_call(
2323 "org.freedesktop.systemd1",
2324 "/org/freedesktop/systemd1",
2325 "org.freedesktop.systemd1.Manager",
2326 "StartTransientUnit");
2330 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2334 r = sd_bus_message_open_container(m, 'a', "(sv)");
2338 if (!isempty(slice)) {
2339 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2344 if (!isempty(description)) {
2345 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2350 if (!isempty(after)) {
2351 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2356 if (!isempty(after2)) {
2357 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2362 /* cgroup empty notification is not available in containers
2363 * currently. To make this less problematic, let's shorten the
2364 * stop timeout for sessions, so that we don't wait
2367 /* Make sure that the session shells are terminated with
2368 * SIGHUP since bash and friends tend to ignore SIGTERM */
2369 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2373 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2377 r = sd_bus_message_close_container(m);
2381 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2385 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2393 r = sd_bus_message_read(reply, "o", &j);
2407 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2408 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2414 r = sd_bus_call_method(
2416 "org.freedesktop.systemd1",
2417 "/org/freedesktop/systemd1",
2418 "org.freedesktop.systemd1.Manager",
2422 "ss", unit, "fail");
2430 r = sd_bus_message_read(reply, "o", &j);
2444 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2445 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2451 r = sd_bus_call_method(
2453 "org.freedesktop.systemd1",
2454 "/org/freedesktop/systemd1",
2455 "org.freedesktop.systemd1.Manager",
2459 "ss", unit, "fail");
2461 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2462 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2467 sd_bus_error_free(error);
2478 r = sd_bus_message_read(reply, "o", &j);
2492 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2493 _cleanup_free_ char *path = NULL;
2499 path = unit_dbus_path_from_name(scope);
2503 r = sd_bus_call_method(
2505 "org.freedesktop.systemd1",
2507 "org.freedesktop.systemd1.Scope",
2513 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2514 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2515 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2516 sd_bus_error_free(error);
2526 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2530 return sd_bus_call_method(
2532 "org.freedesktop.systemd1",
2533 "/org/freedesktop/systemd1",
2534 "org.freedesktop.systemd1.Manager",
2538 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2541 int manager_unit_is_active(Manager *manager, const char *unit) {
2542 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2543 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2544 _cleanup_free_ char *path = NULL;
2551 path = unit_dbus_path_from_name(unit);
2555 r = sd_bus_get_property(
2557 "org.freedesktop.systemd1",
2559 "org.freedesktop.systemd1.Unit",
2565 /* systemd might have droppped off momentarily, let's
2566 * not make this an error */
2567 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2568 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2571 /* If the unit is already unloaded then it's not
2573 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2574 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2580 r = sd_bus_message_read(reply, "s", &state);
2584 return !streq(state, "inactive") && !streq(state, "failed");
2587 int manager_job_is_active(Manager *manager, const char *path) {
2588 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2589 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2595 r = sd_bus_get_property(
2597 "org.freedesktop.systemd1",
2599 "org.freedesktop.systemd1.Job",
2605 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2606 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2609 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2615 /* We don't actually care about the state really. The fact
2616 * that we could read the job state is enough for us */