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"
43 #include "bus-common-errors.h"
44 #include "udev-util.h"
46 static int property_get_idle_hint(
49 const char *interface,
51 sd_bus_message *reply,
53 sd_bus_error *error) {
55 Manager *m = userdata;
61 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
64 static int property_get_idle_since_hint(
67 const char *interface,
69 sd_bus_message *reply,
71 sd_bus_error *error) {
73 Manager *m = userdata;
80 manager_get_idle_hint(m, &t);
82 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
85 static int property_get_inhibited(
88 const char *interface,
90 sd_bus_message *reply,
92 sd_bus_error *error) {
94 Manager *m = userdata;
101 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
103 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
106 static int property_get_preparing(
109 const char *interface,
110 const char *property,
111 sd_bus_message *reply,
113 sd_bus_error *error) {
115 Manager *m = userdata;
122 if (streq(property, "PreparingForShutdown"))
123 b = !!(m->action_what & INHIBIT_SHUTDOWN);
125 b = !!(m->action_what & INHIBIT_SLEEP);
127 return sd_bus_message_append(reply, "b", b);
130 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
132 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
133 _cleanup_free_ char *p = NULL;
134 Manager *m = userdata;
143 r = sd_bus_message_read(message, "s", &name);
147 session = hashmap_get(m->sessions, name);
149 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
151 p = session_bus_path(session);
155 return sd_bus_reply_method_return(message, "o", p);
158 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
159 _cleanup_free_ char *p = NULL;
160 Session *session = NULL;
161 Manager *m = userdata;
169 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
171 r = sd_bus_message_read(message, "u", &pid);
176 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
178 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
182 r = sd_bus_creds_get_pid(creds, &pid);
187 r = manager_get_session_by_pid(m, pid, &session);
191 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
193 p = session_bus_path(session);
197 return sd_bus_reply_method_return(message, "o", p);
200 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
201 _cleanup_free_ char *p = NULL;
202 Manager *m = userdata;
211 r = sd_bus_message_read(message, "u", &uid);
215 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
217 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
219 p = user_bus_path(user);
223 return sd_bus_reply_method_return(message, "o", p);
226 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
227 _cleanup_free_ char *p = NULL;
228 Manager *m = userdata;
237 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
239 r = sd_bus_message_read(message, "u", &pid);
244 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
246 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
250 r = sd_bus_creds_get_pid(creds, &pid);
255 r = manager_get_user_by_pid(m, pid, &user);
259 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);
261 p = user_bus_path(user);
265 return sd_bus_reply_method_return(message, "o", p);
268 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
269 _cleanup_free_ char *p = NULL;
270 Manager *m = userdata;
279 r = sd_bus_message_read(message, "s", &name);
283 seat = hashmap_get(m->seats, name);
285 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
287 p = seat_bus_path(seat);
291 return sd_bus_reply_method_return(message, "o", p);
294 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
295 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
296 Manager *m = userdata;
305 r = sd_bus_message_new_method_return(message, &reply);
309 r = sd_bus_message_open_container(reply, 'a', "(susso)");
313 HASHMAP_FOREACH(session, m->sessions, i) {
314 _cleanup_free_ char *p = NULL;
316 p = session_bus_path(session);
320 r = sd_bus_message_append(reply, "(susso)",
322 (uint32_t) session->user->uid,
324 session->seat ? session->seat->id : "",
330 r = sd_bus_message_close_container(reply);
334 return sd_bus_send(bus, reply, NULL);
337 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
338 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
339 Manager *m = userdata;
348 r = sd_bus_message_new_method_return(message, &reply);
352 r = sd_bus_message_open_container(reply, 'a', "(uso)");
356 HASHMAP_FOREACH(user, m->users, i) {
357 _cleanup_free_ char *p = NULL;
359 p = user_bus_path(user);
363 r = sd_bus_message_append(reply, "(uso)",
364 (uint32_t) user->uid,
371 r = sd_bus_message_close_container(reply);
375 return sd_bus_send(bus, reply, NULL);
378 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
379 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
380 Manager *m = userdata;
389 r = sd_bus_message_new_method_return(message, &reply);
393 r = sd_bus_message_open_container(reply, 'a', "(so)");
397 HASHMAP_FOREACH(seat, m->seats, i) {
398 _cleanup_free_ char *p = NULL;
400 p = seat_bus_path(seat);
404 r = sd_bus_message_append(reply, "(so)", seat->id, p);
409 r = sd_bus_message_close_container(reply);
413 return sd_bus_send(bus, reply, NULL);
416 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
417 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
418 Manager *m = userdata;
419 Inhibitor *inhibitor;
423 r = sd_bus_message_new_method_return(message, &reply);
427 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
431 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
433 r = sd_bus_message_append(reply, "(ssssuu)",
434 strempty(inhibit_what_to_string(inhibitor->what)),
435 strempty(inhibitor->who),
436 strempty(inhibitor->why),
437 strempty(inhibit_mode_to_string(inhibitor->mode)),
438 (uint32_t) inhibitor->uid,
439 (uint32_t) inhibitor->pid);
444 r = sd_bus_message_close_container(reply);
448 return sd_bus_send(bus, reply, NULL);
451 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
452 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
453 uint32_t uid, leader, audit_id = 0;
454 _cleanup_free_ char *id = NULL;
455 Session *session = NULL;
456 Manager *m = userdata;
469 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
474 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
477 t = _SESSION_TYPE_INVALID;
479 t = session_type_from_string(type);
481 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
485 c = _SESSION_CLASS_INVALID;
487 c = session_class_from_string(class);
489 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
492 if (isempty(desktop))
495 if (!string_is_safe(desktop))
496 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
502 seat = hashmap_get(m->seats, cseat);
504 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
507 if (tty_is_vc(tty)) {
512 else if (seat != m->seat0)
513 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);
515 v = vtnr_from_tty(tty);
517 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
521 else if (vtnr != (uint32_t) v)
522 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
524 } else if (tty_is_console(tty)) {
528 else if (seat != m->seat0)
529 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
532 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
536 if (seat_has_vts(seat)) {
537 if (!vtnr || vtnr > 63)
538 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
541 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
545 r = sd_bus_message_enter_container(message, 'a', "(sv)");
549 if (t == _SESSION_TYPE_INVALID) {
550 if (!isempty(display))
552 else if (!isempty(tty))
555 t = SESSION_UNSPECIFIED;
558 if (c == _SESSION_CLASS_INVALID) {
559 if (t == SESSION_UNSPECIFIED)
560 c = SESSION_BACKGROUND;
566 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
568 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
572 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
574 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
579 manager_get_session_by_pid(m, leader, &session);
581 _cleanup_free_ char *path = NULL;
582 _cleanup_close_ int fifo_fd = -1;
584 /* Session already exists, client is probably
585 * something like "su" which changes uid but is still
586 * the same session */
588 fifo_fd = session_create_fifo(session);
592 path = session_bus_path(session);
596 log_debug("Sending reply about an existing session: "
597 "id=%s object_path=%s uid=%u runtime_path=%s "
598 "session_fd=%d seat=%s vtnr=%u",
601 (uint32_t) session->user->uid,
602 session->user->runtime_path,
604 session->seat ? session->seat->id : "",
605 (uint32_t) session->vtnr);
607 return sd_bus_reply_method_return(
611 session->user->runtime_path,
613 (uint32_t) session->user->uid,
614 session->seat ? session->seat->id : "",
615 (uint32_t) session->vtnr,
619 audit_session_from_pid(leader, &audit_id);
621 /* Keep our session IDs and the audit session IDs in sync */
623 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
626 /* Wut? There's already a session by this name and we
627 * didn't find it above? Weird, then let's not trust
628 * the audit data and let's better register a new
630 if (hashmap_get(m->sessions, id)) {
631 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
644 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
647 } while (hashmap_get(m->sessions, id));
650 r = manager_add_user_by_uid(m, uid, &user);
654 r = manager_add_session(m, id, &session);
658 session_set_user(session, user);
660 session->leader = leader;
661 session->audit_id = audit_id;
664 session->remote = remote;
665 session->vtnr = vtnr;
668 session->tty = strdup(tty);
675 if (!isempty(display)) {
676 session->display = strdup(display);
677 if (!session->display) {
683 if (!isempty(remote_user)) {
684 session->remote_user = strdup(remote_user);
685 if (!session->remote_user) {
691 if (!isempty(remote_host)) {
692 session->remote_host = strdup(remote_host);
693 if (!session->remote_host) {
699 if (!isempty(service)) {
700 session->service = strdup(service);
701 if (!session->service) {
707 if (!isempty(desktop)) {
708 session->desktop = strdup(desktop);
709 if (!session->desktop) {
716 r = seat_attach_session(seat, session);
721 r = session_start(session);
725 session->create_message = sd_bus_message_ref(message);
727 /* Now, let's wait until the slice unit and stuff got
728 * created. We send the reply back from
729 * session_send_create_reply(). */
735 session_add_to_gc_queue(session);
738 user_add_to_gc_queue(user);
743 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
744 Manager *m = userdata;
753 r = sd_bus_message_read(message, "s", &name);
757 session = hashmap_get(m->sessions, name);
759 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
761 session_release(session);
763 return sd_bus_reply_method_return(message, NULL);
766 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
767 Manager *m = userdata;
776 r = sd_bus_message_read(message, "s", &name);
780 session = hashmap_get(m->sessions, name);
782 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
784 r = session_activate(session);
788 return sd_bus_reply_method_return(message, NULL);
791 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
792 const char *session_name, *seat_name;
793 Manager *m = userdata;
802 /* Same as ActivateSession() but refuses to work if
803 * the seat doesn't match */
805 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
809 session = hashmap_get(m->sessions, session_name);
811 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", session_name);
813 seat = hashmap_get(m->seats, seat_name);
815 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", seat_name);
817 if (session->seat != seat)
818 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
820 r = session_activate(session);
824 return sd_bus_reply_method_return(message, NULL);
827 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
828 Manager *m = userdata;
837 r = sd_bus_message_read(message, "s", &name);
841 session = hashmap_get(m->sessions, name);
843 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
845 r = session_send_lock(session, streq(sd_bus_message_get_member(message), "LockSession"));
849 return sd_bus_reply_method_return(message, NULL);
852 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
853 Manager *m = userdata;
860 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
864 return sd_bus_reply_method_return(message, NULL);
867 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
868 const char *name, *swho;
869 Manager *m = userdata;
879 r = sd_bus_message_read(message, "ssi", &name, &swho, &signo);
886 who = kill_who_from_string(swho);
888 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
891 if (signo <= 0 || signo >= _NSIG)
892 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
894 session = hashmap_get(m->sessions, name);
896 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
898 r = session_kill(session, who, signo);
902 return sd_bus_reply_method_return(message, NULL);
905 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
906 Manager *m = userdata;
916 r = sd_bus_message_read(message, "ui", &uid, &signo);
920 if (signo <= 0 || signo >= _NSIG)
921 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
923 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
925 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
927 r = user_kill(user, signo);
931 return sd_bus_reply_method_return(message, NULL);
934 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
935 Manager *m = userdata;
944 r = sd_bus_message_read(message, "s", &name);
948 session = hashmap_get(m->sessions, name);
950 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
952 r = session_stop(session, true);
956 return sd_bus_reply_method_return(message, NULL);
959 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
960 Manager *m = userdata;
969 r = sd_bus_message_read(message, "u", &uid);
973 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
975 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
977 r = user_stop(user, true);
981 return sd_bus_reply_method_return(message, NULL);
984 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
985 Manager *m = userdata;
994 r = sd_bus_message_read(message, "s", &name);
998 seat = hashmap_get(m->seats, name);
1000 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
1002 r = seat_stop_sessions(seat, true);
1006 return sd_bus_reply_method_return(message, NULL);
1009 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1010 _cleanup_free_ char *cc = NULL;
1011 Manager *m = userdata;
1022 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1029 return errno ? -errno : -ENOENT;
1031 r = bus_verify_polkit_async(
1034 "org.freedesktop.login1.set-user-linger",
1036 &m->polkit_registry,
1041 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1043 mkdir_p_label("/var/lib/systemd", 0755);
1045 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1049 cc = cescape(pw->pw_name);
1053 path = strappenda("/var/lib/systemd/linger/", cc);
1061 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1068 if (r < 0 && errno != ENOENT)
1071 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1073 user_add_to_gc_queue(u);
1076 return sd_bus_reply_method_return(message, NULL);
1079 static int trigger_device(Manager *m, struct udev_device *d) {
1080 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1081 struct udev_list_entry *first, *item;
1086 e = udev_enumerate_new(m->udev);
1091 r = udev_enumerate_add_match_parent(e, d);
1096 r = udev_enumerate_scan_devices(e);
1100 first = udev_enumerate_get_list_entry(e);
1101 udev_list_entry_foreach(item, first) {
1102 _cleanup_free_ char *t = NULL;
1105 p = udev_list_entry_get_name(item);
1107 t = strappend(p, "/uevent");
1111 write_string_file(t, "change");
1117 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1118 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1119 _cleanup_free_ char *rule = NULL, *file = NULL;
1120 const char *id_for_seat;
1127 d = udev_device_new_from_syspath(m->udev, sysfs);
1131 if (!udev_device_has_tag(d, "seat"))
1134 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1138 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1141 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1144 mkdir_p_label("/etc/udev/rules.d", 0755);
1145 mac_selinux_init("/etc");
1146 r = write_string_file_atomic_label(file, rule);
1150 return trigger_device(m, d);
1153 static int flush_devices(Manager *m) {
1154 _cleanup_closedir_ DIR *d;
1158 d = opendir("/etc/udev/rules.d");
1160 if (errno != ENOENT)
1161 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1165 while ((de = readdir(d))) {
1167 if (!dirent_is_file(de))
1170 if (!startswith(de->d_name, "72-seat-"))
1173 if (!endswith(de->d_name, ".rules"))
1176 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1177 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1181 return trigger_device(m, NULL);
1184 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1185 const char *sysfs, *seat;
1186 Manager *m = userdata;
1193 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1197 if (!path_startswith(sysfs, "/sys"))
1198 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1200 if (!seat_name_is_valid(seat))
1201 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1203 r = bus_verify_polkit_async(
1206 "org.freedesktop.login1.attach-device",
1208 &m->polkit_registry,
1213 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1215 r = attach_device(m, seat, sysfs);
1219 return sd_bus_reply_method_return(message, NULL);
1222 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1223 Manager *m = userdata;
1230 r = sd_bus_message_read(message, "b", &interactive);
1234 r = bus_verify_polkit_async(
1237 "org.freedesktop.login1.flush-devices",
1239 &m->polkit_registry,
1244 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1246 r = flush_devices(m);
1250 return sd_bus_reply_method_return(message, NULL);
1253 static int have_multiple_sessions(
1262 /* Check for other users' sessions. Greeter sessions do not
1263 * count, and non-login sessions do not count either. */
1264 HASHMAP_FOREACH(session, m->sessions, i)
1265 if (session->class == SESSION_USER &&
1266 session->user->uid != uid)
1272 static int bus_manager_log_shutdown(
1275 const char *unit_name) {
1282 if (w != INHIBIT_SHUTDOWN)
1285 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1286 p = "MESSAGE=System is powering down.";
1287 q = "SHUTDOWN=power-off";
1288 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1289 p = "MESSAGE=System is halting.";
1290 q = "SHUTDOWN=halt";
1291 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1292 p = "MESSAGE=System is rebooting.";
1293 q = "SHUTDOWN=reboot";
1294 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1295 p = "MESSAGE=System is rebooting with kexec.";
1296 q = "SHUTDOWN=kexec";
1298 p = "MESSAGE=System is shutting down.";
1302 return log_struct(LOG_NOTICE,
1303 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1309 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1310 Manager *m = userdata;
1315 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1319 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1324 if (until <= now(CLOCK_MONOTONIC))
1327 /* We want to ignore the lid switch for a while after each
1328 * suspend, and after boot-up. Hence let's install a timer for
1329 * this. As long as the event source exists we ignore the lid
1332 if (m->lid_switch_ignore_event_source) {
1335 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1342 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1344 r = sd_event_add_time(
1346 &m->lid_switch_ignore_event_source,
1349 lid_switch_ignore_handler, m);
1354 static int execute_shutdown_or_sleep(
1357 const char *unit_name,
1358 sd_bus_error *error) {
1360 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1367 assert(w < _INHIBIT_WHAT_MAX);
1370 bus_manager_log_shutdown(m, w, unit_name);
1372 r = sd_bus_call_method(
1374 "org.freedesktop.systemd1",
1375 "/org/freedesktop/systemd1",
1376 "org.freedesktop.systemd1.Manager",
1380 "ss", unit_name, "replace-irreversibly");
1384 r = sd_bus_message_read(reply, "o", &p);
1392 m->action_unit = unit_name;
1393 free(m->action_job);
1397 /* Make sure the lid switch is ignored for a while */
1398 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + IGNORE_LID_SWITCH_SUSPEND_USEC);
1403 static int delay_shutdown_or_sleep(
1406 const char *unit_name) {
1410 assert(w < _INHIBIT_WHAT_MAX);
1413 m->action_timestamp = now(CLOCK_MONOTONIC);
1414 m->action_unit = unit_name;
1420 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1422 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1423 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1424 [INHIBIT_SLEEP] = "PrepareForSleep"
1427 int active = _active;
1431 assert(w < _INHIBIT_WHAT_MAX);
1432 assert(signal_name[w]);
1434 return sd_bus_emit_signal(m->bus,
1435 "/org/freedesktop/login1",
1436 "org.freedesktop.login1.Manager",
1442 int bus_manager_shutdown_or_sleep_now_or_later(
1444 const char *unit_name,
1446 sd_bus_error *error) {
1454 assert(w <= _INHIBIT_WHAT_MAX);
1455 assert(!m->action_job);
1457 /* Tell everybody to prepare for shutdown/sleep */
1458 send_prepare_for(m, w, true);
1461 m->inhibit_delay_max > 0 &&
1462 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1465 /* Shutdown is delayed, keep in mind what we
1466 * want to do, and start a timeout */
1467 r = delay_shutdown_or_sleep(m, w, unit_name);
1469 /* Shutdown is not delayed, execute it
1471 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1476 static int method_do_shutdown_or_sleep(
1478 sd_bus_message *message,
1479 const char *unit_name,
1482 const char *action_multiple_sessions,
1483 const char *action_ignore_inhibit,
1484 const char *sleep_verb,
1485 sd_bus_message_handler_t method,
1486 sd_bus_error *error) {
1488 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1489 bool multiple_sessions, blocked;
1497 assert(w <= _INHIBIT_WHAT_MAX);
1499 assert(action_multiple_sessions);
1500 assert(action_ignore_inhibit);
1503 r = sd_bus_message_read(message, "b", &interactive);
1507 /* Don't allow multiple jobs being executed at the same time */
1509 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1512 r = can_sleep(sleep_verb);
1517 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1520 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
1524 r = sd_bus_creds_get_uid(creds, &uid);
1528 r = have_multiple_sessions(m, uid);
1532 multiple_sessions = r > 0;
1533 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1535 if (multiple_sessions) {
1536 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, &m->polkit_registry, error);
1540 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1544 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, &m->polkit_registry, error);
1548 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1551 if (!multiple_sessions && !blocked) {
1552 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, &m->polkit_registry, error);
1556 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1559 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1563 return sd_bus_reply_method_return(message, NULL);
1566 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1567 Manager *m = userdata;
1569 return method_do_shutdown_or_sleep(
1571 SPECIAL_POWEROFF_TARGET,
1573 "org.freedesktop.login1.power-off",
1574 "org.freedesktop.login1.power-off-multiple-sessions",
1575 "org.freedesktop.login1.power-off-ignore-inhibit",
1581 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1582 Manager *m = userdata;
1584 return method_do_shutdown_or_sleep(
1586 SPECIAL_REBOOT_TARGET,
1588 "org.freedesktop.login1.reboot",
1589 "org.freedesktop.login1.reboot-multiple-sessions",
1590 "org.freedesktop.login1.reboot-ignore-inhibit",
1596 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1597 Manager *m = userdata;
1599 return method_do_shutdown_or_sleep(
1601 SPECIAL_SUSPEND_TARGET,
1603 "org.freedesktop.login1.suspend",
1604 "org.freedesktop.login1.suspend-multiple-sessions",
1605 "org.freedesktop.login1.suspend-ignore-inhibit",
1611 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1612 Manager *m = userdata;
1614 return method_do_shutdown_or_sleep(
1616 SPECIAL_HIBERNATE_TARGET,
1618 "org.freedesktop.login1.hibernate",
1619 "org.freedesktop.login1.hibernate-multiple-sessions",
1620 "org.freedesktop.login1.hibernate-ignore-inhibit",
1626 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1627 Manager *m = userdata;
1629 return method_do_shutdown_or_sleep(
1631 SPECIAL_HYBRID_SLEEP_TARGET,
1633 "org.freedesktop.login1.hibernate",
1634 "org.freedesktop.login1.hibernate-multiple-sessions",
1635 "org.freedesktop.login1.hibernate-ignore-inhibit",
1637 method_hybrid_sleep,
1641 static int method_can_shutdown_or_sleep(
1643 sd_bus_message *message,
1646 const char *action_multiple_sessions,
1647 const char *action_ignore_inhibit,
1648 const char *sleep_verb,
1649 sd_bus_error *error) {
1651 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1652 bool multiple_sessions, challenge, blocked;
1653 const char *result = NULL;
1660 assert(w <= _INHIBIT_WHAT_MAX);
1662 assert(action_multiple_sessions);
1663 assert(action_ignore_inhibit);
1666 r = can_sleep(sleep_verb);
1670 return sd_bus_reply_method_return(message, "s", "na");
1673 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
1677 r = sd_bus_creds_get_uid(creds, &uid);
1681 r = have_multiple_sessions(m, uid);
1685 multiple_sessions = r > 0;
1686 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1688 if (multiple_sessions) {
1689 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, false, &challenge, error);
1696 result = "challenge";
1702 r = bus_verify_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, false, &challenge, error);
1706 if (r > 0 && !result)
1708 else if (challenge && (!result || streq(result, "yes")))
1709 result = "challenge";
1714 if (!multiple_sessions && !blocked) {
1715 /* If neither inhibit nor multiple sessions
1716 * apply then just check the normal policy */
1718 r = bus_verify_polkit(message, CAP_SYS_BOOT, action, false, &challenge, error);
1725 result = "challenge";
1730 return sd_bus_reply_method_return(message, "s", result);
1733 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1734 Manager *m = userdata;
1736 return method_can_shutdown_or_sleep(
1739 "org.freedesktop.login1.power-off",
1740 "org.freedesktop.login1.power-off-multiple-sessions",
1741 "org.freedesktop.login1.power-off-ignore-inhibit",
1746 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1747 Manager *m = userdata;
1749 return method_can_shutdown_or_sleep(
1752 "org.freedesktop.login1.reboot",
1753 "org.freedesktop.login1.reboot-multiple-sessions",
1754 "org.freedesktop.login1.reboot-ignore-inhibit",
1759 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1760 Manager *m = userdata;
1762 return method_can_shutdown_or_sleep(
1765 "org.freedesktop.login1.suspend",
1766 "org.freedesktop.login1.suspend-multiple-sessions",
1767 "org.freedesktop.login1.suspend-ignore-inhibit",
1772 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1773 Manager *m = userdata;
1775 return method_can_shutdown_or_sleep(
1778 "org.freedesktop.login1.hibernate",
1779 "org.freedesktop.login1.hibernate-multiple-sessions",
1780 "org.freedesktop.login1.hibernate-ignore-inhibit",
1785 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1786 Manager *m = userdata;
1788 return method_can_shutdown_or_sleep(
1791 "org.freedesktop.login1.hibernate",
1792 "org.freedesktop.login1.hibernate-multiple-sessions",
1793 "org.freedesktop.login1.hibernate-ignore-inhibit",
1798 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1799 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1800 const char *who, *why, *what, *mode;
1801 _cleanup_free_ char *id = NULL;
1802 _cleanup_close_ int fifo_fd = -1;
1803 Manager *m = userdata;
1804 Inhibitor *i = NULL;
1815 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1819 w = inhibit_what_from_string(what);
1821 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1823 mm = inhibit_mode_from_string(mode);
1825 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1827 /* Delay is only supported for shutdown/sleep */
1828 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1829 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1831 /* Don't allow taking delay locks while we are already
1832 * executing the operation. We shouldn't create the impression
1833 * that the lock was successful if the machine is about to go
1834 * down/suspend any moment. */
1835 if (m->action_what & w)
1836 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1838 r = bus_verify_polkit_async(message, CAP_SYS_BOOT,
1839 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1840 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1841 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1842 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1843 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1844 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1845 "org.freedesktop.login1.inhibit-handle-lid-switch",
1846 false, &m->polkit_registry, error);
1850 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1852 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID, &creds);
1856 r = sd_bus_creds_get_uid(creds, &uid);
1860 r = sd_bus_creds_get_pid(creds, &pid);
1868 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1871 } while (hashmap_get(m->inhibitors, id));
1873 r = manager_add_inhibitor(m, id, &i);
1881 i->why = strdup(why);
1882 i->who = strdup(who);
1884 if (!i->why || !i->who) {
1889 fifo_fd = inhibitor_create_fifo(i);
1897 return sd_bus_reply_method_return(message, "h", fifo_fd);
1906 const sd_bus_vtable manager_vtable[] = {
1907 SD_BUS_VTABLE_START(0),
1909 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
1910 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
1911 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
1912 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
1913 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1914 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1915 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1916 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1917 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1918 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
1919 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
1920 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
1921 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
1922 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
1923 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
1924 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
1925 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1926 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1927 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1929 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
1930 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1931 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
1932 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1933 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1934 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
1935 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
1936 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
1937 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
1938 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
1939 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
1940 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
1941 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1942 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, 0),
1943 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, 0),
1944 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, 0),
1945 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, 0),
1946 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1947 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1948 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1949 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1950 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1951 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
1952 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
1953 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
1954 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
1955 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
1956 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
1957 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
1958 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
1959 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
1960 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
1961 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
1962 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
1963 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
1964 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
1966 SD_BUS_SIGNAL("SessionNew", "so", 0),
1967 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
1968 SD_BUS_SIGNAL("UserNew", "uo", 0),
1969 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
1970 SD_BUS_SIGNAL("SeatNew", "so", 0),
1971 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
1972 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
1973 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
1978 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
1987 if (streq(result, "done"))
1988 r = session_send_create_reply(s, NULL);
1990 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
1992 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
1993 r = session_send_create_reply(s, &e);
1999 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2000 const char *path, *result, *unit;
2001 Manager *m = userdata;
2011 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2013 bus_log_parse_error(r);
2017 if (m->action_job && streq(m->action_job, path)) {
2018 log_info("Operation finished.");
2020 /* Tell people that they now may take a lock again */
2021 send_prepare_for(m, m->action_what, false);
2023 free(m->action_job);
2024 m->action_job = NULL;
2025 m->action_unit = NULL;
2030 session = hashmap_get(m->session_units, unit);
2033 if (streq_ptr(path, session->scope_job)) {
2034 free(session->scope_job);
2035 session->scope_job = NULL;
2038 session_jobs_reply(session, unit, result);
2040 session_save(session);
2041 session_add_to_gc_queue(session);
2044 user = hashmap_get(m->user_units, unit);
2047 if (streq_ptr(path, user->service_job)) {
2048 free(user->service_job);
2049 user->service_job = NULL;
2052 if (streq_ptr(path, user->slice_job)) {
2053 free(user->slice_job);
2054 user->slice_job = NULL;
2057 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2058 session_jobs_reply(session, unit, result);
2062 user_add_to_gc_queue(user);
2068 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2069 const char *path, *unit;
2070 Manager *m = userdata;
2079 r = sd_bus_message_read(message, "so", &unit, &path);
2081 bus_log_parse_error(r);
2085 session = hashmap_get(m->session_units, unit);
2087 session_add_to_gc_queue(session);
2089 user = hashmap_get(m->user_units, unit);
2091 user_add_to_gc_queue(user);
2096 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2097 _cleanup_free_ char *unit = NULL;
2098 Manager *m = userdata;
2108 path = sd_bus_message_get_path(message);
2112 r = unit_name_from_dbus_path(path, &unit);
2114 /* quietly ignore non-units paths */
2115 return r == -EINVAL ? 0 : r;
2117 session = hashmap_get(m->session_units, unit);
2119 session_add_to_gc_queue(session);
2121 user = hashmap_get(m->user_units, unit);
2123 user_add_to_gc_queue(user);
2128 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2129 Manager *m = userdata;
2136 r = sd_bus_message_read(message, "b", &b);
2138 bus_log_parse_error(r);
2145 /* systemd finished reloading, let's recheck all our sessions */
2146 log_debug("System manager has been reloaded, rechecking sessions...");
2148 HASHMAP_FOREACH(session, m->sessions, i)
2149 session_add_to_gc_queue(session);
2154 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2155 const char *name, *old, *new;
2156 Manager *m = userdata;
2164 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2166 bus_log_parse_error(r);
2170 if (isempty(old) || !isempty(new))
2173 key = set_remove(m->busnames, (char*) old);
2177 /* Drop all controllers owned by this name */
2181 HASHMAP_FOREACH(session, m->sessions, i)
2182 if (session_is_controller(session, old))
2183 session_drop_controller(session);
2188 int manager_send_changed(Manager *manager, const char *property, ...) {
2193 l = strv_from_stdarg_alloca(property);
2195 return sd_bus_emit_properties_changed_strv(
2197 "/org/freedesktop/login1",
2198 "org.freedesktop.login1.Manager",
2202 int manager_dispatch_delayed(Manager *manager) {
2203 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2204 Inhibitor *offending = NULL;
2209 if (manager->action_what == 0 || manager->action_job)
2212 /* Continue delay? */
2213 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
2214 _cleanup_free_ char *comm = NULL, *u = NULL;
2216 get_process_comm(offending->pid, &comm);
2217 u = uid_to_name(offending->uid);
2219 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2222 log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
2223 offending->uid, strna(u),
2224 offending->pid, strna(comm));
2227 /* Actually do the operation */
2228 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
2230 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2232 manager->action_unit = NULL;
2233 manager->action_what = 0;
2240 int manager_start_scope(
2245 const char *description,
2246 const char *after, const char *after2,
2247 sd_bus_error *error,
2250 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2257 r = sd_bus_message_new_method_call(
2260 "org.freedesktop.systemd1",
2261 "/org/freedesktop/systemd1",
2262 "org.freedesktop.systemd1.Manager",
2263 "StartTransientUnit");
2267 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2271 r = sd_bus_message_open_container(m, 'a', "(sv)");
2275 if (!isempty(slice)) {
2276 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2281 if (!isempty(description)) {
2282 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2287 if (!isempty(after)) {
2288 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2293 if (!isempty(after2)) {
2294 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2299 /* cgroup empty notification is not available in containers
2300 * currently. To make this less problematic, let's shorten the
2301 * stop timeout for sessions, so that we don't wait
2304 /* Make sure that the session shells are terminated with
2305 * SIGHUP since bash and friends tend to ignore SIGTERM */
2306 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2310 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2314 r = sd_bus_message_close_container(m);
2318 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2322 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2330 r = sd_bus_message_read(reply, "o", &j);
2344 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2345 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2351 r = sd_bus_call_method(
2353 "org.freedesktop.systemd1",
2354 "/org/freedesktop/systemd1",
2355 "org.freedesktop.systemd1.Manager",
2359 "ss", unit, "fail");
2367 r = sd_bus_message_read(reply, "o", &j);
2381 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2382 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2388 r = sd_bus_call_method(
2390 "org.freedesktop.systemd1",
2391 "/org/freedesktop/systemd1",
2392 "org.freedesktop.systemd1.Manager",
2396 "ss", unit, "fail");
2398 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2399 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2404 sd_bus_error_free(error);
2415 r = sd_bus_message_read(reply, "o", &j);
2429 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2430 _cleanup_free_ char *path = NULL;
2436 path = unit_dbus_path_from_name(scope);
2440 r = sd_bus_call_method(
2442 "org.freedesktop.systemd1",
2444 "org.freedesktop.systemd1.Scope",
2450 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2451 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2452 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2453 sd_bus_error_free(error);
2463 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2467 return sd_bus_call_method(
2469 "org.freedesktop.systemd1",
2470 "/org/freedesktop/systemd1",
2471 "org.freedesktop.systemd1.Manager",
2475 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2478 int manager_unit_is_active(Manager *manager, const char *unit) {
2479 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2480 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2481 _cleanup_free_ char *path = NULL;
2488 path = unit_dbus_path_from_name(unit);
2492 r = sd_bus_get_property(
2494 "org.freedesktop.systemd1",
2496 "org.freedesktop.systemd1.Unit",
2502 /* systemd might have droppped off momentarily, let's
2503 * not make this an error */
2504 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2505 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2508 /* If the unit is already unloaded then it's not
2510 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2511 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2517 r = sd_bus_message_read(reply, "s", &state);
2521 return !streq(state, "inactive") && !streq(state, "failed");
2524 int manager_job_is_active(Manager *manager, const char *path) {
2525 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2526 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2532 r = sd_bus_get_property(
2534 "org.freedesktop.systemd1",
2536 "org.freedesktop.systemd1.Job",
2542 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2543 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2546 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2552 /* We don't actually care about the state really. The fact
2553 * that we could read the job state is enough for us */