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/>.
26 #include <sys/capability.h>
29 #include "sd-messages.h"
32 #include "path-util.h"
34 #include "sleep-config.h"
35 #include "fileio-label.h"
38 #include "unit-name.h"
42 #include "bus-error.h"
44 #include "bus-errors.h"
45 #include "udev-util.h"
47 static int property_get_idle_hint(
50 const char *interface,
52 sd_bus_message *reply,
54 sd_bus_error *error) {
56 Manager *m = userdata;
62 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
65 static int property_get_idle_since_hint(
68 const char *interface,
70 sd_bus_message *reply,
72 sd_bus_error *error) {
74 Manager *m = userdata;
81 manager_get_idle_hint(m, &t);
83 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
86 static int property_get_inhibited(
89 const char *interface,
91 sd_bus_message *reply,
93 sd_bus_error *error) {
95 Manager *m = userdata;
102 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
104 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
107 static int property_get_preparing(
110 const char *interface,
111 const char *property,
112 sd_bus_message *reply,
114 sd_bus_error *error) {
116 Manager *m = userdata;
123 if (streq(property, "PreparingForShutdown"))
124 b = !!(m->action_what & INHIBIT_SHUTDOWN);
126 b = !!(m->action_what & INHIBIT_SLEEP);
128 return sd_bus_message_append(reply, "b", b);
131 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
133 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
134 _cleanup_free_ char *p = NULL;
135 Manager *m = userdata;
144 r = sd_bus_message_read(message, "s", &name);
148 session = hashmap_get(m->sessions, name);
150 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
152 p = session_bus_path(session);
156 return sd_bus_reply_method_return(message, "o", p);
159 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
160 _cleanup_free_ char *p = NULL;
161 Session *session = NULL;
162 Manager *m = userdata;
170 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
172 r = sd_bus_message_read(message, "u", &pid);
177 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
179 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
183 r = sd_bus_creds_get_pid(creds, &pid);
188 r = manager_get_session_by_pid(m, pid, &session);
192 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
194 p = session_bus_path(session);
198 return sd_bus_reply_method_return(message, "o", p);
201 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
202 _cleanup_free_ char *p = NULL;
203 Manager *m = userdata;
212 r = sd_bus_message_read(message, "u", &uid);
216 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
218 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
220 p = user_bus_path(user);
224 return sd_bus_reply_method_return(message, "o", p);
227 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
228 _cleanup_free_ char *p = NULL;
229 Manager *m = userdata;
238 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
240 r = sd_bus_message_read(message, "u", &pid);
245 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
247 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
251 r = sd_bus_creds_get_pid(creds, &pid);
256 r = manager_get_user_by_pid(m, pid, &user);
260 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);
262 p = user_bus_path(user);
266 return sd_bus_reply_method_return(message, "o", p);
269 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
270 _cleanup_free_ char *p = NULL;
271 Manager *m = userdata;
280 r = sd_bus_message_read(message, "s", &name);
284 seat = hashmap_get(m->seats, name);
286 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
288 p = seat_bus_path(seat);
292 return sd_bus_reply_method_return(message, "o", p);
295 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
296 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
297 Manager *m = userdata;
306 r = sd_bus_message_new_method_return(message, &reply);
310 r = sd_bus_message_open_container(reply, 'a', "(susso)");
314 HASHMAP_FOREACH(session, m->sessions, i) {
315 _cleanup_free_ char *p = NULL;
317 p = session_bus_path(session);
321 r = sd_bus_message_append(reply, "(susso)",
323 (uint32_t) session->user->uid,
325 session->seat ? session->seat->id : "",
331 r = sd_bus_message_close_container(reply);
335 return sd_bus_send(bus, reply, NULL);
338 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
339 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
340 Manager *m = userdata;
349 r = sd_bus_message_new_method_return(message, &reply);
353 r = sd_bus_message_open_container(reply, 'a', "(uso)");
357 HASHMAP_FOREACH(user, m->users, i) {
358 _cleanup_free_ char *p = NULL;
360 p = user_bus_path(user);
364 r = sd_bus_message_append(reply, "(uso)",
365 (uint32_t) user->uid,
372 r = sd_bus_message_close_container(reply);
376 return sd_bus_send(bus, reply, NULL);
379 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
380 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
381 Manager *m = userdata;
390 r = sd_bus_message_new_method_return(message, &reply);
394 r = sd_bus_message_open_container(reply, 'a', "(so)");
398 HASHMAP_FOREACH(seat, m->seats, i) {
399 _cleanup_free_ char *p = NULL;
401 p = seat_bus_path(seat);
405 r = sd_bus_message_append(reply, "(so)", seat->id, p);
410 r = sd_bus_message_close_container(reply);
414 return sd_bus_send(bus, reply, NULL);
417 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
418 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
419 Manager *m = userdata;
420 Inhibitor *inhibitor;
424 r = sd_bus_message_new_method_return(message, &reply);
428 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
432 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
434 r = sd_bus_message_append(reply, "(ssssuu)",
435 strempty(inhibit_what_to_string(inhibitor->what)),
436 strempty(inhibitor->who),
437 strempty(inhibitor->why),
438 strempty(inhibit_mode_to_string(inhibitor->mode)),
439 (uint32_t) inhibitor->uid,
440 (uint32_t) inhibitor->pid);
445 r = sd_bus_message_close_container(reply);
449 return sd_bus_send(bus, reply, NULL);
452 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
453 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
454 uint32_t uid, leader, audit_id = 0;
455 _cleanup_free_ char *id = NULL;
456 Session *session = NULL;
457 Manager *m = userdata;
470 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
475 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
478 t = _SESSION_TYPE_INVALID;
480 t = session_type_from_string(type);
482 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
486 c = _SESSION_CLASS_INVALID;
488 c = session_class_from_string(class);
490 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
493 if (isempty(desktop))
496 if (!string_is_safe(desktop))
497 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
503 seat = hashmap_get(m->seats, cseat);
505 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
508 if (tty_is_vc(tty)) {
513 else if (seat != m->seat0)
514 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);
516 v = vtnr_from_tty(tty);
518 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
522 else if (vtnr != (uint32_t) v)
523 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
525 } else if (tty_is_console(tty)) {
529 else if (seat != m->seat0)
530 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
533 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
537 if (seat_has_vts(seat)) {
538 if (!vtnr || vtnr > 63)
539 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
542 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
546 r = sd_bus_message_enter_container(message, 'a', "(sv)");
550 if (t == _SESSION_TYPE_INVALID) {
551 if (!isempty(display))
553 else if (!isempty(tty))
556 t = SESSION_UNSPECIFIED;
559 if (c == _SESSION_CLASS_INVALID) {
560 if (t == SESSION_UNSPECIFIED)
561 c = SESSION_BACKGROUND;
567 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
569 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
573 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
575 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
580 manager_get_session_by_pid(m, leader, &session);
582 _cleanup_free_ char *path = NULL;
583 _cleanup_close_ int fifo_fd = -1;
585 /* Session already exists, client is probably
586 * something like "su" which changes uid but is still
587 * the same session */
589 fifo_fd = session_create_fifo(session);
593 path = session_bus_path(session);
597 log_debug("Sending reply about an existing session: "
598 "id=%s object_path=%s uid=%u runtime_path=%s "
599 "session_fd=%d seat=%s vtnr=%u",
602 (uint32_t) session->user->uid,
603 session->user->runtime_path,
605 session->seat ? session->seat->id : "",
606 (uint32_t) session->vtnr);
608 return sd_bus_reply_method_return(
612 session->user->runtime_path,
614 (uint32_t) session->user->uid,
615 session->seat ? session->seat->id : "",
616 (uint32_t) session->vtnr,
620 audit_session_from_pid(leader, &audit_id);
622 /* Keep our session IDs and the audit session IDs in sync */
624 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
627 /* Wut? There's already a session by this name and we
628 * didn't find it above? Weird, then let's not trust
629 * the audit data and let's better register a new
631 if (hashmap_get(m->sessions, id)) {
632 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
645 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
648 } while (hashmap_get(m->sessions, id));
651 r = manager_add_user_by_uid(m, uid, &user);
655 r = manager_add_session(m, id, &session);
659 session_set_user(session, user);
661 session->leader = leader;
662 session->audit_id = audit_id;
665 session->remote = remote;
666 session->vtnr = vtnr;
669 session->tty = strdup(tty);
676 if (!isempty(display)) {
677 session->display = strdup(display);
678 if (!session->display) {
684 if (!isempty(remote_user)) {
685 session->remote_user = strdup(remote_user);
686 if (!session->remote_user) {
692 if (!isempty(remote_host)) {
693 session->remote_host = strdup(remote_host);
694 if (!session->remote_host) {
700 if (!isempty(service)) {
701 session->service = strdup(service);
702 if (!session->service) {
708 if (!isempty(desktop)) {
709 session->desktop = strdup(desktop);
710 if (!session->desktop) {
717 r = seat_attach_session(seat, session);
722 r = session_start(session);
726 session->create_message = sd_bus_message_ref(message);
728 /* Now, let's wait until the slice unit and stuff got
729 * created. We send the reply back from
730 * session_send_create_reply().*/
736 session_add_to_gc_queue(session);
739 user_add_to_gc_queue(user);
744 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
745 Manager *m = userdata;
754 r = sd_bus_message_read(message, "s", &name);
758 session = hashmap_get(m->sessions, name);
760 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
762 session_release(session);
764 return sd_bus_reply_method_return(message, NULL);
767 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
768 Manager *m = userdata;
777 r = sd_bus_message_read(message, "s", &name);
781 session = hashmap_get(m->sessions, name);
783 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
785 r = session_activate(session);
789 return sd_bus_reply_method_return(message, NULL);
792 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
793 const char *session_name, *seat_name;
794 Manager *m = userdata;
803 /* Same as ActivateSession() but refuses to work if
804 * the seat doesn't match */
806 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
810 session = hashmap_get(m->sessions, session_name);
812 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", session_name);
814 seat = hashmap_get(m->seats, seat_name);
816 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", seat_name);
818 if (session->seat != seat)
819 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
821 r = session_activate(session);
825 return sd_bus_reply_method_return(message, NULL);
828 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
829 Manager *m = userdata;
838 r = sd_bus_message_read(message, "s", &name);
842 session = hashmap_get(m->sessions, name);
844 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
846 r = session_send_lock(session, streq(sd_bus_message_get_member(message), "LockSession"));
850 return sd_bus_reply_method_return(message, NULL);
853 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
854 Manager *m = userdata;
861 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
865 return sd_bus_reply_method_return(message, NULL);
868 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
869 const char *name, *swho;
870 Manager *m = userdata;
880 r = sd_bus_message_read(message, "ssi", &name, &swho, &signo);
887 who = kill_who_from_string(swho);
889 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
892 if (signo <= 0 || signo >= _NSIG)
893 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
895 session = hashmap_get(m->sessions, name);
897 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
899 r = session_kill(session, who, signo);
903 return sd_bus_reply_method_return(message, NULL);
906 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
907 Manager *m = userdata;
917 r = sd_bus_message_read(message, "ui", &uid, &signo);
921 if (signo <= 0 || signo >= _NSIG)
922 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
924 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
926 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
928 r = user_kill(user, signo);
932 return sd_bus_reply_method_return(message, NULL);
935 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
936 Manager *m = userdata;
945 r = sd_bus_message_read(message, "s", &name);
949 session = hashmap_get(m->sessions, name);
951 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
953 r = session_stop(session, true);
957 return sd_bus_reply_method_return(message, NULL);
960 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
961 Manager *m = userdata;
970 r = sd_bus_message_read(message, "u", &uid);
974 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
976 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
978 r = user_stop(user, true);
982 return sd_bus_reply_method_return(message, NULL);
985 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
986 Manager *m = userdata;
995 r = sd_bus_message_read(message, "s", &name);
999 seat = hashmap_get(m->seats, name);
1001 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
1003 r = seat_stop_sessions(seat, true);
1007 return sd_bus_reply_method_return(message, NULL);
1010 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1011 _cleanup_free_ char *cc = NULL;
1012 Manager *m = userdata;
1023 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1030 return errno ? -errno : -ENOENT;
1032 r = bus_verify_polkit_async(bus,
1033 &m->polkit_registry,
1036 "org.freedesktop.login1.set-user-linger",
1039 method_set_user_linger, m);
1043 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1045 mkdir_p_label("/var/lib/systemd", 0755);
1047 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1051 cc = cescape(pw->pw_name);
1055 path = strappenda("/var/lib/systemd/linger/", cc);
1063 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1070 if (r < 0 && errno != ENOENT)
1073 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1075 user_add_to_gc_queue(u);
1078 return sd_bus_reply_method_return(message, NULL);
1081 static int trigger_device(Manager *m, struct udev_device *d) {
1082 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1083 struct udev_list_entry *first, *item;
1088 e = udev_enumerate_new(m->udev);
1093 r = udev_enumerate_add_match_parent(e, d);
1098 r = udev_enumerate_scan_devices(e);
1102 first = udev_enumerate_get_list_entry(e);
1103 udev_list_entry_foreach(item, first) {
1104 _cleanup_free_ char *t = NULL;
1107 p = udev_list_entry_get_name(item);
1109 t = strappend(p, "/uevent");
1113 write_string_file(t, "change");
1119 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1120 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1121 _cleanup_free_ char *rule = NULL, *file = NULL;
1122 const char *id_for_seat;
1129 d = udev_device_new_from_syspath(m->udev, sysfs);
1133 if (!udev_device_has_tag(d, "seat"))
1136 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1140 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1143 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1146 mkdir_p_label("/etc/udev/rules.d", 0755);
1148 r = write_string_file_atomic_label(file, rule);
1152 return trigger_device(m, d);
1155 static int flush_devices(Manager *m) {
1156 _cleanup_closedir_ DIR *d;
1160 d = opendir("/etc/udev/rules.d");
1162 if (errno != ENOENT)
1163 log_warning("Failed to open /etc/udev/rules.d: %m");
1167 while ((de = readdir(d))) {
1169 if (!dirent_is_file(de))
1172 if (!startswith(de->d_name, "72-seat-"))
1175 if (!endswith(de->d_name, ".rules"))
1178 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1179 log_warning("Failed to unlink %s: %m", de->d_name);
1183 return trigger_device(m, NULL);
1186 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1187 const char *sysfs, *seat;
1188 Manager *m = userdata;
1195 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1199 if (!path_startswith(sysfs, "/sys"))
1200 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1202 if (!seat_name_is_valid(seat))
1203 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1205 r = bus_verify_polkit_async(bus,
1206 &m->polkit_registry,
1209 "org.freedesktop.login1.attach-device",
1212 method_attach_device, m);
1216 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1218 r = attach_device(m, seat, sysfs);
1222 return sd_bus_reply_method_return(message, NULL);
1225 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1226 Manager *m = userdata;
1233 r = sd_bus_message_read(message, "b", &interactive);
1237 r = bus_verify_polkit_async(bus,
1238 &m->polkit_registry,
1241 "org.freedesktop.login1.flush-devices",
1244 method_flush_devices, m);
1248 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1250 r = flush_devices(m);
1254 return sd_bus_reply_method_return(message, NULL);
1257 static int have_multiple_sessions(
1266 /* Check for other users' sessions. Greeter sessions do not
1267 * count, and non-login sessions do not count either. */
1268 HASHMAP_FOREACH(session, m->sessions, i)
1269 if (session->class == SESSION_USER &&
1270 session->user->uid != uid)
1276 static int bus_manager_log_shutdown(
1279 const char *unit_name) {
1286 if (w != INHIBIT_SHUTDOWN)
1289 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1290 p = "MESSAGE=System is powering down.";
1291 q = "SHUTDOWN=power-off";
1292 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1293 p = "MESSAGE=System is halting.";
1294 q = "SHUTDOWN=halt";
1295 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1296 p = "MESSAGE=System is rebooting.";
1297 q = "SHUTDOWN=reboot";
1298 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1299 p = "MESSAGE=System is rebooting with kexec.";
1300 q = "SHUTDOWN=kexec";
1302 p = "MESSAGE=System is shutting down.";
1306 return log_struct(LOG_NOTICE, MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1311 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1312 Manager *m = userdata;
1317 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1321 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1326 if (until <= now(CLOCK_MONOTONIC))
1329 /* We want to ignore the lid switch for a while after each
1330 * suspend, and after boot-up. Hence let's install a timer for
1331 * this. As long as the event source exists we ignore the lid
1334 if (m->lid_switch_ignore_event_source) {
1337 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1344 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1346 r = sd_event_add_time(
1348 &m->lid_switch_ignore_event_source,
1351 lid_switch_ignore_handler, m);
1356 static int execute_shutdown_or_sleep(
1359 const char *unit_name,
1360 sd_bus_error *error) {
1362 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1369 assert(w < _INHIBIT_WHAT_MAX);
1372 bus_manager_log_shutdown(m, w, unit_name);
1374 r = sd_bus_call_method(
1376 "org.freedesktop.systemd1",
1377 "/org/freedesktop/systemd1",
1378 "org.freedesktop.systemd1.Manager",
1382 "ss", unit_name, "replace-irreversibly");
1386 r = sd_bus_message_read(reply, "o", &p);
1394 m->action_unit = unit_name;
1395 free(m->action_job);
1399 /* Make sure the lid switch is ignored for a while */
1400 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + IGNORE_LID_SWITCH_SUSPEND_USEC);
1405 static int delay_shutdown_or_sleep(
1408 const char *unit_name) {
1412 assert(w < _INHIBIT_WHAT_MAX);
1415 m->action_timestamp = now(CLOCK_MONOTONIC);
1416 m->action_unit = unit_name;
1422 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1424 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1425 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1426 [INHIBIT_SLEEP] = "PrepareForSleep"
1429 int active = _active;
1433 assert(w < _INHIBIT_WHAT_MAX);
1434 assert(signal_name[w]);
1436 return sd_bus_emit_signal(m->bus,
1437 "/org/freedesktop/login1",
1438 "org.freedesktop.login1.Manager",
1444 int bus_manager_shutdown_or_sleep_now_or_later(
1446 const char *unit_name,
1448 sd_bus_error *error) {
1456 assert(w <= _INHIBIT_WHAT_MAX);
1457 assert(!m->action_job);
1459 /* Tell everybody to prepare for shutdown/sleep */
1460 send_prepare_for(m, w, true);
1463 m->inhibit_delay_max > 0 &&
1464 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1467 /* Shutdown is delayed, keep in mind what we
1468 * want to do, and start a timeout */
1469 r = delay_shutdown_or_sleep(m, w, unit_name);
1471 /* Shutdown is not delayed, execute it
1473 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1478 static int method_do_shutdown_or_sleep(
1480 sd_bus_message *message,
1481 const char *unit_name,
1484 const char *action_multiple_sessions,
1485 const char *action_ignore_inhibit,
1486 const char *sleep_verb,
1487 sd_bus_message_handler_t method,
1488 sd_bus_error *error) {
1490 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1491 bool multiple_sessions, blocked;
1499 assert(w <= _INHIBIT_WHAT_MAX);
1501 assert(action_multiple_sessions);
1502 assert(action_ignore_inhibit);
1505 r = sd_bus_message_read(message, "b", &interactive);
1509 /* Don't allow multiple jobs being executed at the same time */
1511 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1514 r = can_sleep(sleep_verb);
1519 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1522 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
1526 r = sd_bus_creds_get_uid(creds, &uid);
1530 r = have_multiple_sessions(m, uid);
1534 multiple_sessions = r > 0;
1535 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1537 if (multiple_sessions) {
1538 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT,
1539 action_multiple_sessions, interactive, error, method, m);
1543 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1547 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT,
1548 action_ignore_inhibit, interactive, error, method, m);
1552 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1555 if (!multiple_sessions && !blocked) {
1556 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message, CAP_SYS_BOOT,
1557 action, interactive, error, method, m);
1561 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1564 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1568 return sd_bus_reply_method_return(message, NULL);
1571 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1572 Manager *m = userdata;
1574 return method_do_shutdown_or_sleep(
1576 SPECIAL_POWEROFF_TARGET,
1578 "org.freedesktop.login1.power-off",
1579 "org.freedesktop.login1.power-off-multiple-sessions",
1580 "org.freedesktop.login1.power-off-ignore-inhibit",
1586 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1587 Manager *m = userdata;
1589 return method_do_shutdown_or_sleep(
1591 SPECIAL_REBOOT_TARGET,
1593 "org.freedesktop.login1.reboot",
1594 "org.freedesktop.login1.reboot-multiple-sessions",
1595 "org.freedesktop.login1.reboot-ignore-inhibit",
1601 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1602 Manager *m = userdata;
1604 return method_do_shutdown_or_sleep(
1606 SPECIAL_SUSPEND_TARGET,
1608 "org.freedesktop.login1.suspend",
1609 "org.freedesktop.login1.suspend-multiple-sessions",
1610 "org.freedesktop.login1.suspend-ignore-inhibit",
1616 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1617 Manager *m = userdata;
1619 return method_do_shutdown_or_sleep(
1621 SPECIAL_HIBERNATE_TARGET,
1623 "org.freedesktop.login1.hibernate",
1624 "org.freedesktop.login1.hibernate-multiple-sessions",
1625 "org.freedesktop.login1.hibernate-ignore-inhibit",
1631 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1632 Manager *m = userdata;
1634 return method_do_shutdown_or_sleep(
1636 SPECIAL_HYBRID_SLEEP_TARGET,
1638 "org.freedesktop.login1.hibernate",
1639 "org.freedesktop.login1.hibernate-multiple-sessions",
1640 "org.freedesktop.login1.hibernate-ignore-inhibit",
1642 method_hybrid_sleep,
1646 static int method_can_shutdown_or_sleep(
1648 sd_bus_message *message,
1651 const char *action_multiple_sessions,
1652 const char *action_ignore_inhibit,
1653 const char *sleep_verb,
1654 sd_bus_error *error) {
1656 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1657 bool multiple_sessions, challenge, blocked;
1658 const char *result = NULL;
1665 assert(w <= _INHIBIT_WHAT_MAX);
1667 assert(action_multiple_sessions);
1668 assert(action_ignore_inhibit);
1671 r = can_sleep(sleep_verb);
1675 return sd_bus_reply_method_return(message, "s", "na");
1678 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
1682 r = sd_bus_creds_get_uid(creds, &uid);
1686 r = have_multiple_sessions(m, uid);
1690 multiple_sessions = r > 0;
1691 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1693 if (multiple_sessions) {
1694 r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action_multiple_sessions, false, &challenge, error);
1701 result = "challenge";
1707 r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action_ignore_inhibit, false, &challenge, error);
1711 if (r > 0 && !result)
1713 else if (challenge && (!result || streq(result, "yes")))
1714 result = "challenge";
1719 if (!multiple_sessions && !blocked) {
1720 /* If neither inhibit nor multiple sessions
1721 * apply then just check the normal policy */
1723 r = bus_verify_polkit(m->bus, message, CAP_SYS_BOOT, action, false, &challenge, error);
1730 result = "challenge";
1735 return sd_bus_reply_method_return(message, "s", result);
1738 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1739 Manager *m = userdata;
1741 return method_can_shutdown_or_sleep(
1744 "org.freedesktop.login1.power-off",
1745 "org.freedesktop.login1.power-off-multiple-sessions",
1746 "org.freedesktop.login1.power-off-ignore-inhibit",
1751 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1752 Manager *m = userdata;
1754 return method_can_shutdown_or_sleep(
1757 "org.freedesktop.login1.reboot",
1758 "org.freedesktop.login1.reboot-multiple-sessions",
1759 "org.freedesktop.login1.reboot-ignore-inhibit",
1764 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1765 Manager *m = userdata;
1767 return method_can_shutdown_or_sleep(
1770 "org.freedesktop.login1.suspend",
1771 "org.freedesktop.login1.suspend-multiple-sessions",
1772 "org.freedesktop.login1.suspend-ignore-inhibit",
1777 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1778 Manager *m = userdata;
1780 return method_can_shutdown_or_sleep(
1783 "org.freedesktop.login1.hibernate",
1784 "org.freedesktop.login1.hibernate-multiple-sessions",
1785 "org.freedesktop.login1.hibernate-ignore-inhibit",
1790 static int method_can_hybrid_sleep(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.hibernate",
1797 "org.freedesktop.login1.hibernate-multiple-sessions",
1798 "org.freedesktop.login1.hibernate-ignore-inhibit",
1803 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1804 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1805 const char *who, *why, *what, *mode;
1806 _cleanup_free_ char *id = NULL;
1807 _cleanup_close_ int fifo_fd = -1;
1808 Manager *m = userdata;
1809 Inhibitor *i = NULL;
1820 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1824 w = inhibit_what_from_string(what);
1826 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1828 mm = inhibit_mode_from_string(mode);
1830 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1832 /* Delay is only supported for shutdown/sleep */
1833 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1834 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1836 /* Don't allow taking delay locks while we are already
1837 * executing the operation. We shouldn't create the impression
1838 * that the lock was successful if the machine is about to go
1839 * down/suspend any moment. */
1840 if (m->action_what & w)
1841 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1843 r = bus_verify_polkit_async(bus, &m->polkit_registry, message, CAP_SYS_BOOT,
1844 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1845 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1846 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1847 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1848 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1849 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1850 "org.freedesktop.login1.inhibit-handle-lid-switch",
1851 false, error, method_inhibit, m);
1855 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1857 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID, &creds);
1861 r = sd_bus_creds_get_uid(creds, &uid);
1865 r = sd_bus_creds_get_pid(creds, &pid);
1873 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1876 } while (hashmap_get(m->inhibitors, id));
1878 r = manager_add_inhibitor(m, id, &i);
1886 i->why = strdup(why);
1887 i->who = strdup(who);
1889 if (!i->why || !i->who) {
1894 fifo_fd = inhibitor_create_fifo(i);
1902 return sd_bus_reply_method_return(message, "h", fifo_fd);
1911 const sd_bus_vtable manager_vtable[] = {
1912 SD_BUS_VTABLE_START(0),
1914 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
1915 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
1916 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
1917 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
1918 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1919 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1920 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1921 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1922 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1923 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
1924 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
1925 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
1926 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
1927 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
1928 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
1929 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1930 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1931 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1933 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
1934 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1935 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
1936 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1937 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1938 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
1939 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
1940 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
1941 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
1942 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
1943 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
1944 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
1945 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
1946 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, 0),
1947 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, 0),
1948 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, 0),
1949 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, 0),
1950 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1951 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1952 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1953 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1954 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
1955 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
1956 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
1957 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
1958 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
1959 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
1960 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
1961 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
1962 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
1963 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
1964 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
1965 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
1966 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
1967 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
1968 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
1970 SD_BUS_SIGNAL("SessionNew", "so", 0),
1971 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
1972 SD_BUS_SIGNAL("UserNew", "uo", 0),
1973 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
1974 SD_BUS_SIGNAL("SeatNew", "so", 0),
1975 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
1976 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
1977 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
1982 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
1991 if (streq(result, "done"))
1992 r = session_send_create_reply(s, NULL);
1994 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
1996 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
1997 r = session_send_create_reply(s, &e);
2003 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2004 const char *path, *result, *unit;
2005 Manager *m = userdata;
2015 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2017 bus_log_parse_error(r);
2021 if (m->action_job && streq(m->action_job, path)) {
2022 log_info("Operation finished.");
2024 /* Tell people that they now may take a lock again */
2025 send_prepare_for(m, m->action_what, false);
2027 free(m->action_job);
2028 m->action_job = NULL;
2029 m->action_unit = NULL;
2034 session = hashmap_get(m->session_units, unit);
2037 if (streq_ptr(path, session->scope_job)) {
2038 free(session->scope_job);
2039 session->scope_job = NULL;
2042 session_jobs_reply(session, unit, result);
2044 session_save(session);
2045 session_add_to_gc_queue(session);
2048 user = hashmap_get(m->user_units, unit);
2051 if (streq_ptr(path, user->service_job)) {
2052 free(user->service_job);
2053 user->service_job = NULL;
2056 if (streq_ptr(path, user->slice_job)) {
2057 free(user->slice_job);
2058 user->slice_job = NULL;
2061 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2062 session_jobs_reply(session, unit, result);
2066 user_add_to_gc_queue(user);
2072 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2073 const char *path, *unit;
2074 Manager *m = userdata;
2083 r = sd_bus_message_read(message, "so", &unit, &path);
2085 bus_log_parse_error(r);
2089 session = hashmap_get(m->session_units, unit);
2091 session_add_to_gc_queue(session);
2093 user = hashmap_get(m->user_units, unit);
2095 user_add_to_gc_queue(user);
2100 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2101 _cleanup_free_ char *unit = NULL;
2102 Manager *m = userdata;
2112 path = sd_bus_message_get_path(message);
2116 r = unit_name_from_dbus_path(path, &unit);
2118 /* quietly ignore non-units paths */
2119 return r == -EINVAL ? 0 : r;
2121 session = hashmap_get(m->session_units, unit);
2123 session_add_to_gc_queue(session);
2125 user = hashmap_get(m->user_units, unit);
2127 user_add_to_gc_queue(user);
2132 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2133 Manager *m = userdata;
2140 r = sd_bus_message_read(message, "b", &b);
2142 bus_log_parse_error(r);
2149 /* systemd finished reloading, let's recheck all our sessions */
2150 log_debug("System manager has been reloaded, rechecking sessions...");
2152 HASHMAP_FOREACH(session, m->sessions, i)
2153 session_add_to_gc_queue(session);
2158 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2159 const char *name, *old, *new;
2160 Manager *m = userdata;
2168 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2170 bus_log_parse_error(r);
2174 if (isempty(old) || !isempty(new))
2177 key = set_remove(m->busnames, (char*) old);
2181 /* Drop all controllers owned by this name */
2185 HASHMAP_FOREACH(session, m->sessions, i)
2186 if (session_is_controller(session, old))
2187 session_drop_controller(session);
2192 int manager_send_changed(Manager *manager, const char *property, ...) {
2197 l = strv_from_stdarg_alloca(property);
2199 return sd_bus_emit_properties_changed_strv(
2201 "/org/freedesktop/login1",
2202 "org.freedesktop.login1.Manager",
2206 int manager_dispatch_delayed(Manager *manager) {
2207 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2208 Inhibitor *offending = NULL;
2213 if (manager->action_what == 0 || manager->action_job)
2216 /* Continue delay? */
2217 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
2218 _cleanup_free_ char *comm = NULL, *u = NULL;
2220 get_process_comm(offending->pid, &comm);
2221 u = uid_to_name(offending->uid);
2223 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2226 log_info("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
2227 offending->uid, strna(u),
2228 offending->pid, strna(comm));
2231 /* Actually do the operation */
2232 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
2234 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2236 manager->action_unit = NULL;
2237 manager->action_what = 0;
2244 int manager_start_scope(
2249 const char *description,
2250 const char *after, const char *after2,
2251 sd_bus_error *error,
2254 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2261 r = sd_bus_message_new_method_call(
2264 "org.freedesktop.systemd1",
2265 "/org/freedesktop/systemd1",
2266 "org.freedesktop.systemd1.Manager",
2267 "StartTransientUnit");
2271 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2275 r = sd_bus_message_open_container(m, 'a', "(sv)");
2279 if (!isempty(slice)) {
2280 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2285 if (!isempty(description)) {
2286 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2291 if (!isempty(after)) {
2292 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2297 if (!isempty(after2)) {
2298 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2303 /* cgroup empty notification is not available in containers
2304 * currently. To make this less problematic, let's shorten the
2305 * stop timeout for sessions, so that we don't wait
2308 /* Make sure that the session shells are terminated with
2309 * SIGHUP since bash and friends tend to ignore SIGTERM */
2310 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2314 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2318 r = sd_bus_message_close_container(m);
2322 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2326 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2334 r = sd_bus_message_read(reply, "o", &j);
2348 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2349 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2355 r = sd_bus_call_method(
2357 "org.freedesktop.systemd1",
2358 "/org/freedesktop/systemd1",
2359 "org.freedesktop.systemd1.Manager",
2363 "ss", unit, "fail");
2371 r = sd_bus_message_read(reply, "o", &j);
2385 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2386 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2392 r = sd_bus_call_method(
2394 "org.freedesktop.systemd1",
2395 "/org/freedesktop/systemd1",
2396 "org.freedesktop.systemd1.Manager",
2400 "ss", unit, "fail");
2402 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2403 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2408 sd_bus_error_free(error);
2419 r = sd_bus_message_read(reply, "o", &j);
2433 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2434 _cleanup_free_ char *path = NULL;
2440 path = unit_dbus_path_from_name(scope);
2444 r = sd_bus_call_method(
2446 "org.freedesktop.systemd1",
2448 "org.freedesktop.systemd1.Scope",
2454 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2455 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2456 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2457 sd_bus_error_free(error);
2467 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2471 return sd_bus_call_method(
2473 "org.freedesktop.systemd1",
2474 "/org/freedesktop/systemd1",
2475 "org.freedesktop.systemd1.Manager",
2479 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2482 int manager_unit_is_active(Manager *manager, const char *unit) {
2483 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2484 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2485 _cleanup_free_ char *path = NULL;
2492 path = unit_dbus_path_from_name(unit);
2496 r = sd_bus_get_property(
2498 "org.freedesktop.systemd1",
2500 "org.freedesktop.systemd1.Unit",
2506 /* systemd might have droppped off momentarily, let's
2507 * not make this an error */
2508 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2509 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2512 /* If the unit is already unloaded then it's not
2514 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2515 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2521 r = sd_bus_message_read(reply, "s", &state);
2525 return !streq(state, "inactive") && !streq(state, "failed");
2528 int manager_job_is_active(Manager *manager, const char *path) {
2529 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2530 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2536 r = sd_bus_get_property(
2538 "org.freedesktop.systemd1",
2540 "org.freedesktop.systemd1.Job",
2546 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2547 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2550 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2556 /* We don't actually care about the state really. The fact
2557 * that we could read the job state is enough for us */