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 "dbus-common.h"
31 #include "path-util.h"
34 #include "systemd/sd-id128.h"
35 #include "systemd/sd-messages.h"
37 #define BUS_MANAGER_INTERFACE \
38 " <interface name=\"org.freedesktop.login1.Manager\">\n" \
39 " <method name=\"GetSession\">\n" \
40 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
41 " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
43 " <method name=\"GetSessionByPID\">\n" \
44 " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
45 " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
47 " <method name=\"GetUser\">\n" \
48 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
49 " <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
51 " <method name=\"GetSeat\">\n" \
52 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
53 " <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
55 " <method name=\"ListSessions\">\n" \
56 " <arg name=\"sessions\" type=\"a(susso)\" direction=\"out\"/>\n" \
58 " <method name=\"ListUsers\">\n" \
59 " <arg name=\"users\" type=\"a(uso)\" direction=\"out\"/>\n" \
61 " <method name=\"ListSeats\">\n" \
62 " <arg name=\"seats\" type=\"a(so)\" direction=\"out\"/>\n" \
64 " <method name=\"CreateSession\">\n" \
65 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
66 " <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n" \
67 " <arg name=\"sevice\" type=\"s\" direction=\"in\"/>\n" \
68 " <arg name=\"type\" type=\"s\" direction=\"in\"/>\n" \
69 " <arg name=\"class\" type=\"s\" direction=\"in\"/>\n" \
70 " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
71 " <arg name=\"vtnr\" type=\"u\" direction=\"in\"/>\n" \
72 " <arg name=\"tty\" type=\"s\" direction=\"in\"/>\n" \
73 " <arg name=\"display\" type=\"s\" direction=\"in\"/>\n" \
74 " <arg name=\"remote\" type=\"b\" direction=\"in\"/>\n" \
75 " <arg name=\"remote_user\" type=\"s\" direction=\"in\"/>\n" \
76 " <arg name=\"remote_host\" type=\"s\" direction=\"in\"/>\n" \
77 " <arg name=\"controllers\" type=\"as\" direction=\"in\"/>\n" \
78 " <arg name=\"reset_controllers\" type=\"as\" direction=\"in\"/>\n" \
79 " <arg name=\"kill_processes\" type=\"b\" direction=\"in\"/>\n" \
80 " <arg name=\"id\" type=\"s\" direction=\"out\"/>\n" \
81 " <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
82 " <arg name=\"runtime_path\" type=\"o\" direction=\"out\"/>\n" \
83 " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
84 " <arg name=\"seat\" type=\"s\" direction=\"out\"/>\n" \
85 " <arg name=\"vtnr\" type=\"u\" direction=\"out\"/>\n" \
87 " <method name=\"ReleaseSession\">\n" \
88 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
90 " <method name=\"ActivateSession\">\n" \
91 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
93 " <method name=\"ActivateSessionOnSeat\">\n" \
94 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
95 " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
97 " <method name=\"LockSession\">\n" \
98 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
100 " <method name=\"UnlockSession\">\n" \
101 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
103 " <method name=\"LockSessions\"/>\n" \
104 " <method name=\"KillSession\">\n" \
105 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
106 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
107 " <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n" \
109 " <method name=\"KillUser\">\n" \
110 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
111 " <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n" \
113 " <method name=\"TerminateSession\">\n" \
114 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
116 " <method name=\"TerminateUser\">\n" \
117 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
119 " <method name=\"TerminateSeat\">\n" \
120 " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
122 " <method name=\"SetUserLinger\">\n" \
123 " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
124 " <arg name=\"b\" type=\"b\" direction=\"in\"/>\n" \
125 " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
127 " <method name=\"AttachDevice\">\n" \
128 " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
129 " <arg name=\"sysfs\" type=\"s\" direction=\"in\"/>\n" \
130 " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
132 " <method name=\"FlushDevices\">\n" \
133 " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
135 " <method name=\"PowerOff\">\n" \
136 " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
138 " <method name=\"Reboot\">\n" \
139 " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
141 " <method name=\"Suspend\">\n" \
142 " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
144 " <method name=\"Hibernate\">\n" \
145 " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
147 " <method name=\"CanPowerOff\">\n" \
148 " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
150 " <method name=\"CanReboot\">\n" \
151 " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
153 " <method name=\"CanSuspend\">\n" \
154 " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
156 " <method name=\"CanHibernate\">\n" \
157 " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
159 " <method name=\"Inhibit\">\n" \
160 " <arg name=\"what\" type=\"s\" direction=\"in\"/>\n" \
161 " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
162 " <arg name=\"why\" type=\"s\" direction=\"in\"/>\n" \
163 " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
164 " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
166 " <method name=\"ListInhibitors\">\n" \
167 " <arg name=\"inhibitors\" type=\"a(ssssuu)\" direction=\"out\"/>\n" \
169 " <signal name=\"SessionNew\">\n" \
170 " <arg name=\"id\" type=\"s\"/>\n" \
171 " <arg name=\"path\" type=\"o\"/>\n" \
173 " <signal name=\"SessionRemoved\">\n" \
174 " <arg name=\"id\" type=\"s\"/>\n" \
175 " <arg name=\"path\" type=\"o\"/>\n" \
177 " <signal name=\"UserNew\">\n" \
178 " <arg name=\"uid\" type=\"u\"/>\n" \
179 " <arg name=\"path\" type=\"o\"/>\n" \
181 " <signal name=\"UserRemoved\">\n" \
182 " <arg name=\"uid\" type=\"u\"/>\n" \
183 " <arg name=\"path\" type=\"o\"/>\n" \
185 " <signal name=\"SeatNew\">\n" \
186 " <arg name=\"id\" type=\"s\"/>\n" \
187 " <arg name=\"path\" type=\"o\"/>\n" \
189 " <signal name=\"SeatRemoved\">\n" \
190 " <arg name=\"id\" type=\"s\"/>\n" \
191 " <arg name=\"path\" type=\"o\"/>\n" \
193 " <signal name=\"PrepareForShutdown\">\n" \
194 " <arg name=\"active\" type=\"b\"/>\n" \
196 " <signal name=\"PrepareForSleep\">\n" \
197 " <arg name=\"active\" type=\"b\"/>\n" \
199 " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
200 " <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
201 " <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
202 " <property name=\"NAutoVTs\" type=\"u\" access=\"read\"/>\n" \
203 " <property name=\"KillOnlyUsers\" type=\"as\" access=\"read\"/>\n" \
204 " <property name=\"KillExcludeUsers\" type=\"as\" access=\"read\"/>\n" \
205 " <property name=\"KillUserProcesses\" type=\"b\" access=\"read\"/>\n" \
206 " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
207 " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
208 " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
209 " <property name=\"BlockInhibited\" type=\"s\" access=\"read\"/>\n" \
210 " <property name=\"DelayInhibited\" type=\"s\" access=\"read\"/>\n" \
211 " <property name=\"InhibitDelayMaxUSec\" type=\"t\" access=\"read\"/>\n" \
212 " <property name=\"HandlePowerKey\" type=\"s\" access=\"read\"/>\n" \
213 " <property name=\"HandleSleepKey\" type=\"s\" access=\"read\"/>\n" \
214 " <property name=\"HandleLidSwitch\" type=\"s\" access=\"read\"/>\n" \
215 " <property name=\"PreparingForShutdown\" type=\"b\" access=\"read\"/>\n" \
216 " <property name=\"PreparingForSleep\" type=\"b\" access=\"read\"/>\n" \
219 #define INTROSPECTION_BEGIN \
220 DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
222 BUS_MANAGER_INTERFACE \
223 BUS_PROPERTIES_INTERFACE \
225 BUS_INTROSPECTABLE_INTERFACE
227 #define INTROSPECTION_END \
230 #define INTERFACES_LIST \
231 BUS_GENERIC_INTERFACES_LIST \
232 "org.freedesktop.login1.Manager\0"
234 static int bus_manager_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
242 b = manager_get_idle_hint(m, NULL) > 0;
243 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
249 static int bus_manager_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
258 manager_get_idle_hint(m, &t);
259 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
261 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
267 static int bus_manager_append_inhibited(DBusMessageIter *i, const char *property, void *data) {
272 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
273 p = inhibit_what_to_string(w);
275 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &p))
281 static int bus_manager_append_preparing(DBusMessageIter *i, const char *property, void *data) {
288 if (streq(property, "PreparingForShutdown"))
289 b = !!(m->delayed_what & INHIBIT_SHUTDOWN);
291 b = !!(m->delayed_what & INHIBIT_SLEEP);
293 dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b);
297 static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMessage **_reply) {
298 Session *session = NULL;
300 const char *type, *class, *seat, *tty, *display, *remote_user, *remote_host, *service;
301 uint32_t uid, leader, audit_id = 0;
302 dbus_bool_t remote, kill_processes;
303 char **controllers = NULL, **reset_controllers = NULL;
307 DBusMessageIter iter;
312 DBusMessage *reply = NULL;
319 if (!dbus_message_iter_init(message, &iter) ||
320 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
323 dbus_message_iter_get_basic(&iter, &uid);
325 if (!dbus_message_iter_next(&iter) ||
326 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
329 dbus_message_iter_get_basic(&iter, &leader);
332 !dbus_message_iter_next(&iter) ||
333 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
336 dbus_message_iter_get_basic(&iter, &service);
338 if (!dbus_message_iter_next(&iter) ||
339 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
342 dbus_message_iter_get_basic(&iter, &type);
343 t = session_type_from_string(type);
346 !dbus_message_iter_next(&iter) ||
347 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
350 dbus_message_iter_get_basic(&iter, &class);
354 c = session_class_from_string(class);
357 !dbus_message_iter_next(&iter) ||
358 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
361 dbus_message_iter_get_basic(&iter, &seat);
366 s = hashmap_get(m->seats, seat);
371 if (!dbus_message_iter_next(&iter) ||
372 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
375 dbus_message_iter_get_basic(&iter, &vtnr);
377 if (!dbus_message_iter_next(&iter) ||
378 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
381 dbus_message_iter_get_basic(&iter, &tty);
383 if (tty_is_vc(tty)) {
388 else if (s != m->vtconsole)
391 v = vtnr_from_tty(tty);
394 return v < 0 ? v : -EINVAL;
398 else if (vtnr != (uint32_t) v)
400 } else if (tty_is_console(tty)) {
404 else if (s != m->vtconsole)
410 } else if (!isempty(tty) && s && seat_is_vtconsole(s))
414 if (seat_can_multi_session(s)) {
423 if (!dbus_message_iter_next(&iter) ||
424 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
427 dbus_message_iter_get_basic(&iter, &display);
429 if (!dbus_message_iter_next(&iter) ||
430 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
433 dbus_message_iter_get_basic(&iter, &remote);
435 if (!dbus_message_iter_next(&iter) ||
436 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
439 dbus_message_iter_get_basic(&iter, &remote_user);
441 if (!dbus_message_iter_next(&iter) ||
442 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
445 dbus_message_iter_get_basic(&iter, &remote_host);
447 if (!dbus_message_iter_next(&iter) ||
448 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
449 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING)
452 r = bus_parse_strv_iter(&iter, &controllers);
456 if (strv_contains(controllers, "systemd") ||
457 !dbus_message_iter_next(&iter) ||
458 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
459 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) {
464 r = bus_parse_strv_iter(&iter, &reset_controllers);
468 if (strv_contains(reset_controllers, "systemd") ||
469 !dbus_message_iter_next(&iter) ||
470 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
475 dbus_message_iter_get_basic(&iter, &kill_processes);
477 r = manager_add_user_by_uid(m, uid, &user);
481 audit_session_from_pid(leader, &audit_id);
484 asprintf(&id, "%lu", (unsigned long) audit_id);
491 session = hashmap_get(m->sessions, id);
496 fifo_fd = session_create_fifo(session);
502 /* Session already exists, client is probably
503 * something like "su" which changes uid but
504 * is still the same audit session */
506 reply = dbus_message_new_method_return(message);
512 p = session_bus_path(session);
518 seat = session->seat ? session->seat->id : "";
519 vtnr = session->vtnr;
520 b = dbus_message_append_args(
522 DBUS_TYPE_STRING, &session->id,
523 DBUS_TYPE_OBJECT_PATH, &p,
524 DBUS_TYPE_STRING, &session->user->runtime_path,
525 DBUS_TYPE_UNIX_FD, &fifo_fd,
526 DBUS_TYPE_STRING, &seat,
527 DBUS_TYPE_UINT32, &vtnr,
536 close_nointr_nofail(fifo_fd);
539 strv_free(controllers);
540 strv_free(reset_controllers);
550 if (asprintf(&id, "c%lu", ++m->session_counter) < 0) {
555 } while (hashmap_get(m->sessions, id));
558 r = manager_add_session(m, user, id, &session);
563 session->leader = leader;
564 session->audit_id = audit_id;
567 session->remote = remote;
568 session->controllers = controllers;
569 session->reset_controllers = reset_controllers;
570 session->kill_processes = kill_processes;
571 session->vtnr = vtnr;
573 controllers = reset_controllers = NULL;
576 session->tty = strdup(tty);
583 if (!isempty(display)) {
584 session->display = strdup(display);
585 if (!session->display) {
591 if (!isempty(remote_user)) {
592 session->remote_user = strdup(remote_user);
593 if (!session->remote_user) {
599 if (!isempty(remote_host)) {
600 session->remote_host = strdup(remote_host);
601 if (!session->remote_host) {
607 if (!isempty(service)) {
608 session->service = strdup(service);
609 if (!session->service) {
615 fifo_fd = session_create_fifo(session);
622 r = seat_attach_session(s, session);
627 r = session_start(session);
631 reply = dbus_message_new_method_return(message);
637 p = session_bus_path(session);
643 seat = s ? s->id : "";
644 b = dbus_message_append_args(
646 DBUS_TYPE_STRING, &session->id,
647 DBUS_TYPE_OBJECT_PATH, &p,
648 DBUS_TYPE_STRING, &session->user->runtime_path,
649 DBUS_TYPE_UNIX_FD, &fifo_fd,
650 DBUS_TYPE_STRING, &seat,
651 DBUS_TYPE_UINT32, &vtnr,
660 close_nointr_nofail(fifo_fd);
666 strv_free(controllers);
667 strv_free(reset_controllers);
670 session_add_to_gc_queue(session);
673 user_add_to_gc_queue(user);
676 close_nointr_nofail(fifo_fd);
679 dbus_message_unref(reply);
684 static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessage *message, DBusError *error, DBusMessage **_reply) {
687 const char *who, *why, *what, *mode;
693 DBusMessage *reply = NULL;
701 if (!dbus_message_get_args(
704 DBUS_TYPE_STRING, &what,
705 DBUS_TYPE_STRING, &who,
706 DBUS_TYPE_STRING, &why,
707 DBUS_TYPE_STRING, &mode,
708 DBUS_TYPE_INVALID)) {
713 w = inhibit_what_from_string(what);
719 mm = inhibit_mode_from_string(mode);
725 /* Delay is only supported for shutdown/sleep */
726 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) {
731 r = verify_polkit(connection, message,
732 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
733 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
734 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
735 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
736 w == INHIBIT_HANDLE_SLEEP_KEY ? "org.freedesktop.login1.inhibit-handle-sleep-key" :
737 "org.freedesktop.login1.inhibit-handle-lid-switch",
742 ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
743 if (ul == (unsigned long) -1) {
748 pid = bus_get_unix_process_id(connection, dbus_message_get_sender(message), error);
758 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0) {
762 } while (hashmap_get(m->inhibitors, id));
764 r = manager_add_inhibitor(m, id, &i);
774 i->why = strdup(why);
775 i->who = strdup(who);
777 if (!i->why || !i->who) {
782 fifo_fd = inhibitor_create_fifo(i);
788 reply = dbus_message_new_method_return(message);
794 if (!dbus_message_append_args(
796 DBUS_TYPE_UNIX_FD, &fifo_fd,
797 DBUS_TYPE_INVALID)) {
802 close_nointr_nofail(fifo_fd);
814 close_nointr_nofail(fifo_fd);
817 dbus_message_unref(reply);
822 static int trigger_device(Manager *m, struct udev_device *d) {
823 struct udev_enumerate *e;
824 struct udev_list_entry *first, *item;
829 e = udev_enumerate_new(m->udev);
836 if (udev_enumerate_add_match_parent(e, d) < 0) {
842 if (udev_enumerate_scan_devices(e) < 0) {
847 first = udev_enumerate_get_list_entry(e);
848 udev_list_entry_foreach(item, first) {
852 p = udev_list_entry_get_name(item);
854 t = strappend(p, "/uevent");
860 write_one_line_file(t, "change");
868 udev_enumerate_unref(e);
873 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
874 struct udev_device *d;
875 char *rule = NULL, *file = NULL;
876 const char *id_for_seat;
883 d = udev_device_new_from_syspath(m->udev, sysfs);
887 if (!udev_device_has_tag(d, "seat")) {
892 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
898 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0) {
903 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) {
908 mkdir_p_label("/etc/udev/rules.d", 0755);
909 r = write_one_line_file_atomic(file, rule);
913 r = trigger_device(m, d);
920 udev_device_unref(d);
925 static int flush_devices(Manager *m) {
930 d = opendir("/etc/udev/rules.d");
933 log_warning("Failed to open /etc/udev/rules.d: %m");
937 while ((de = readdir(d))) {
939 if (!dirent_is_file(de))
942 if (!startswith(de->d_name, "72-seat-"))
945 if (!endswith(de->d_name, ".rules"))
948 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
949 log_warning("Failed to unlink %s: %m", de->d_name);
955 return trigger_device(m, NULL);
958 static int have_multiple_sessions(
959 DBusConnection *connection,
961 DBusMessage *message,
970 ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
971 if (ul == (unsigned long) -1)
974 /* Check for other users' sessions. Greeter sessions do not count. */
975 HASHMAP_FOREACH(session, m->sessions, i)
976 if (session->class == SESSION_USER && session->user->uid != ul)
982 static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) {
983 const char *mode = "replace";
987 return bus_method_call_with_reply (
989 "org.freedesktop.systemd1",
990 "/org/freedesktop/systemd1",
991 "org.freedesktop.systemd1.Manager",
995 DBUS_TYPE_STRING, &unit_name,
996 DBUS_TYPE_STRING, &mode,
1000 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1001 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1002 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1003 [INHIBIT_SLEEP] = "PrepareForSleep"
1006 dbus_bool_t active = _active;
1007 DBusMessage *message;
1012 assert(w < _INHIBIT_WHAT_MAX);
1013 assert(signal_name[w]);
1015 message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]);
1019 if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID) ||
1020 !dbus_connection_send(m->bus, message, NULL))
1023 dbus_message_unref(message);
1027 static int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, const char *unit_name) {
1030 assert(w < _INHIBIT_WHAT_MAX);
1032 /* Tell everybody to prepare for shutdown/sleep */
1033 send_prepare_for(m, w, true);
1035 /* Update timestamp for timeout */
1036 if (!m->delayed_unit)
1037 m->delayed_timestamp = now(CLOCK_MONOTONIC);
1039 /* Remember what we want to do, possibly overriding what kind
1040 * of unit we previously queued. */
1041 m->delayed_unit = unit_name;
1042 m->delayed_what = w;
1047 static int bus_manager_can_shutdown_or_sleep(
1049 DBusConnection *connection,
1050 DBusMessage *message,
1053 const char *action_multiple_sessions,
1054 const char *action_ignore_inhibit,
1055 const char *sleep_type,
1057 DBusMessage **_reply) {
1059 bool multiple_sessions, challenge, blocked, b;
1061 DBusMessage *reply = NULL;
1068 assert(w <= _INHIBIT_WHAT_MAX);
1070 assert(action_multiple_sessions);
1071 assert(action_ignore_inhibit);
1076 r = can_sleep(sleep_type);
1086 r = have_multiple_sessions(connection, m, message, error);
1090 multiple_sessions = r > 0;
1091 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false);
1093 if (multiple_sessions) {
1094 r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
1101 result = "challenge";
1107 r = verify_polkit(connection, message, action_ignore_inhibit, false, &challenge, error);
1111 if (r > 0 && !result)
1113 else if (challenge && (!result || streq(result, "yes")))
1114 result = "challenge";
1119 if (!multiple_sessions && !blocked) {
1120 /* If neither inhibit nor multiple sessions
1121 * apply then just check the normal policy */
1123 r = verify_polkit(connection, message, action, false, &challenge, error);
1130 result = "challenge";
1136 reply = dbus_message_new_method_return(message);
1140 b = dbus_message_append_args(
1142 DBUS_TYPE_STRING, &result,
1145 dbus_message_unref(reply);
1153 static int bus_manager_log_shutdown(
1156 const char *unit_name) {
1163 if (w != INHIBIT_SHUTDOWN)
1166 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1167 p = "MESSAGE=System is powering down.";
1168 q = "SHUTDOWN=power-off";
1169 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1170 p = "MESSAGE=System is halting.";
1171 q = "SHUTDOWN=halt";
1172 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1173 p = "MESSAGE=System is rebooting.";
1174 q = "SHUTDOWN=reboot";
1175 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1176 p = "MESSAGE=System is rebooting with kexec.";
1177 q = "SHUTDOWN=kexec";
1179 p = "MESSAGE=System is shutting down.";
1183 return log_struct(LOG_NOTICE,
1184 "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(SD_MESSAGE_SHUTDOWN),
1189 int bus_manager_shutdown_or_sleep_now_or_later(
1191 const char *unit_name,
1201 assert(w <= _INHIBIT_WHAT_MAX);
1204 m->inhibit_delay_max > 0 &&
1205 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false);
1208 /* Shutdown is delayed, keep in mind what we
1209 * want to do, and start a timeout */
1210 r = delay_shutdown_or_sleep(m, w, unit_name);
1212 bus_manager_log_shutdown(m, w, unit_name);
1214 /* Shutdown is not delayed, execute it
1216 r = send_start_unit(m->bus, unit_name, error);
1222 static int bus_manager_do_shutdown_or_sleep(
1224 DBusConnection *connection,
1225 DBusMessage *message,
1226 const char *unit_name,
1229 const char *action_multiple_sessions,
1230 const char *action_ignore_inhibit,
1231 const char *sleep_type,
1233 DBusMessage **_reply) {
1235 dbus_bool_t interactive;
1236 bool multiple_sessions, blocked;
1237 DBusMessage *reply = NULL;
1245 assert(w <= _INHIBIT_WHAT_MAX);
1247 assert(action_multiple_sessions);
1248 assert(action_ignore_inhibit);
1252 if (!dbus_message_get_args(
1255 DBUS_TYPE_BOOLEAN, &interactive,
1260 r = can_sleep(sleep_type);
1268 r = have_multiple_sessions(connection, m, message, error);
1272 multiple_sessions = r > 0;
1273 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false);
1275 if (multiple_sessions) {
1276 r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
1282 r = verify_polkit(connection, message, action_ignore_inhibit, interactive, NULL, error);
1287 if (!multiple_sessions && !blocked) {
1288 r = verify_polkit(connection, message, action, interactive, NULL, error);
1293 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1297 reply = dbus_message_new_method_return(message);
1305 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_button, handle_button, HandleButton);
1307 static const BusProperty bus_login_manager_properties[] = {
1308 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_path), true },
1309 { "Controllers", bus_property_append_strv, "as", offsetof(Manager, controllers), true },
1310 { "ResetControllers", bus_property_append_strv, "as", offsetof(Manager, reset_controllers), true },
1311 { "NAutoVTs", bus_property_append_unsigned, "u", offsetof(Manager, n_autovts) },
1312 { "KillOnlyUsers", bus_property_append_strv, "as", offsetof(Manager, kill_only_users), true },
1313 { "KillExcludeUsers", bus_property_append_strv, "as", offsetof(Manager, kill_exclude_users), true },
1314 { "KillUserProcesses", bus_property_append_bool, "b", offsetof(Manager, kill_user_processes) },
1315 { "IdleHint", bus_manager_append_idle_hint, "b", 0 },
1316 { "IdleSinceHint", bus_manager_append_idle_hint_since, "t", 0 },
1317 { "IdleSinceHintMonotonic", bus_manager_append_idle_hint_since, "t", 0 },
1318 { "BlockInhibited", bus_manager_append_inhibited, "s", 0 },
1319 { "DelayInhibited", bus_manager_append_inhibited, "s", 0 },
1320 { "InhibitDelayMaxUSec", bus_property_append_usec, "t", offsetof(Manager, inhibit_delay_max) },
1321 { "HandlePowerKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_power_key) },
1322 { "HandleSleepKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_sleep_key) },
1323 { "HandleLidSwitch", bus_manager_append_handle_button, "s", offsetof(Manager, handle_lid_switch) },
1324 { "PreparingForShutdown", bus_manager_append_preparing, "b", 0 },
1325 { "PreparingForSleep", bus_manager_append_preparing, "b", 0 },
1329 static DBusHandlerResult manager_message_handler(
1330 DBusConnection *connection,
1331 DBusMessage *message,
1334 Manager *m = userdata;
1337 DBusMessage *reply = NULL;
1344 dbus_error_init(&error);
1346 if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSession")) {
1352 if (!dbus_message_get_args(
1355 DBUS_TYPE_STRING, &name,
1357 return bus_send_error_reply(connection, message, &error, -EINVAL);
1359 session = hashmap_get(m->sessions, name);
1361 return bus_send_error_reply(connection, message, &error, -ENOENT);
1363 reply = dbus_message_new_method_return(message);
1367 p = session_bus_path(session);
1371 b = dbus_message_append_args(
1373 DBUS_TYPE_OBJECT_PATH, &p,
1380 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSessionByPID")) {
1386 if (!dbus_message_get_args(
1389 DBUS_TYPE_UINT32, &pid,
1391 return bus_send_error_reply(connection, message, &error, -EINVAL);
1393 r = manager_get_session_by_pid(m, pid, &session);
1395 return bus_send_error_reply(connection, message, NULL, r < 0 ? r : -ENOENT);
1397 reply = dbus_message_new_method_return(message);
1401 p = session_bus_path(session);
1405 b = dbus_message_append_args(
1407 DBUS_TYPE_OBJECT_PATH, &p,
1414 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetUser")) {
1420 if (!dbus_message_get_args(
1423 DBUS_TYPE_UINT32, &uid,
1425 return bus_send_error_reply(connection, message, &error, -EINVAL);
1427 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1429 return bus_send_error_reply(connection, message, &error, -ENOENT);
1431 reply = dbus_message_new_method_return(message);
1435 p = user_bus_path(user);
1439 b = dbus_message_append_args(
1441 DBUS_TYPE_OBJECT_PATH, &p,
1448 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSeat")) {
1454 if (!dbus_message_get_args(
1457 DBUS_TYPE_STRING, &name,
1459 return bus_send_error_reply(connection, message, &error, -EINVAL);
1461 seat = hashmap_get(m->seats, name);
1463 return bus_send_error_reply(connection, message, &error, -ENOENT);
1465 reply = dbus_message_new_method_return(message);
1469 p = seat_bus_path(seat);
1473 b = dbus_message_append_args(
1475 DBUS_TYPE_OBJECT_PATH, &p,
1482 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSessions")) {
1486 DBusMessageIter iter, sub;
1487 const char *empty = "";
1489 reply = dbus_message_new_method_return(message);
1493 dbus_message_iter_init_append(reply, &iter);
1495 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(susso)", &sub))
1498 HASHMAP_FOREACH(session, m->sessions, i) {
1499 DBusMessageIter sub2;
1502 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1505 uid = session->user->uid;
1507 p = session_bus_path(session);
1511 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
1512 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
1513 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->user->name) ||
1514 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, session->seat ? (const char**) &session->seat->id : &empty) ||
1515 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
1522 if (!dbus_message_iter_close_container(&sub, &sub2))
1526 if (!dbus_message_iter_close_container(&iter, &sub))
1529 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListUsers")) {
1533 DBusMessageIter iter, sub;
1535 reply = dbus_message_new_method_return(message);
1539 dbus_message_iter_init_append(reply, &iter);
1541 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(uso)", &sub))
1544 HASHMAP_FOREACH(user, m->users, i) {
1545 DBusMessageIter sub2;
1548 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1553 p = user_bus_path(user);
1557 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
1558 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &user->name) ||
1559 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
1566 if (!dbus_message_iter_close_container(&sub, &sub2))
1570 if (!dbus_message_iter_close_container(&iter, &sub))
1573 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSeats")) {
1577 DBusMessageIter iter, sub;
1579 reply = dbus_message_new_method_return(message);
1583 dbus_message_iter_init_append(reply, &iter);
1585 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(so)", &sub))
1588 HASHMAP_FOREACH(seat, m->seats, i) {
1589 DBusMessageIter sub2;
1591 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1594 p = seat_bus_path(seat);
1598 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &seat->id) ||
1599 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
1606 if (!dbus_message_iter_close_container(&sub, &sub2))
1610 if (!dbus_message_iter_close_container(&iter, &sub))
1613 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListInhibitors")) {
1614 Inhibitor *inhibitor;
1616 DBusMessageIter iter, sub;
1618 reply = dbus_message_new_method_return(message);
1622 dbus_message_iter_init_append(reply, &iter);
1624 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssuu)", &sub))
1627 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
1628 DBusMessageIter sub2;
1629 dbus_uint32_t uid, pid;
1630 const char *what, *who, *why, *mode;
1632 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1635 what = strempty(inhibit_what_to_string(inhibitor->what));
1636 who = strempty(inhibitor->who);
1637 why = strempty(inhibitor->why);
1638 mode = strempty(inhibit_mode_to_string(inhibitor->mode));
1639 uid = (dbus_uint32_t) inhibitor->uid;
1640 pid = (dbus_uint32_t) inhibitor->pid;
1642 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &what) ||
1643 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &who) ||
1644 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &why) ||
1645 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &mode) ||
1646 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
1647 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid))
1650 if (!dbus_message_iter_close_container(&sub, &sub2))
1654 if (!dbus_message_iter_close_container(&iter, &sub))
1657 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Inhibit")) {
1659 r = bus_manager_inhibit(m, connection, message, &error, &reply);
1662 return bus_send_error_reply(connection, message, &error, r);
1665 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CreateSession")) {
1667 r = bus_manager_create_session(m, message, &reply);
1669 /* Don't delay the work on OOM here, since it might be
1670 * triggered by a low RLIMIT_NOFILE here (since we
1671 * send a dupped fd to the client), and we'd rather
1672 * see this fail quickly then be retried later */
1675 return bus_send_error_reply(connection, message, NULL, r);
1677 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ReleaseSession")) {
1681 if (!dbus_message_get_args(
1684 DBUS_TYPE_STRING, &name,
1686 return bus_send_error_reply(connection, message, &error, -EINVAL);
1688 session = hashmap_get(m->sessions, name);
1690 return bus_send_error_reply(connection, message, &error, -ENOENT);
1692 /* We use the FIFO to detect stray sessions where the
1693 process invoking PAM dies abnormally. We need to make
1694 sure that that process is not killed if at the clean
1695 end of the session it closes the FIFO. Hence, with
1696 this call explicitly turn off the FIFO logic, so that
1697 the PAM code can finish clean up on its own */
1698 session_remove_fifo(session);
1700 reply = dbus_message_new_method_return(message);
1704 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSession")) {
1708 if (!dbus_message_get_args(
1711 DBUS_TYPE_STRING, &name,
1713 return bus_send_error_reply(connection, message, &error, -EINVAL);
1715 session = hashmap_get(m->sessions, name);
1717 return bus_send_error_reply(connection, message, &error, -ENOENT);
1719 r = session_activate(session);
1721 return bus_send_error_reply(connection, message, NULL, r);
1723 reply = dbus_message_new_method_return(message);
1727 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSessionOnSeat")) {
1728 const char *session_name, *seat_name;
1732 /* Same as ActivateSession() but refuses to work if
1733 * the seat doesn't match */
1735 if (!dbus_message_get_args(
1738 DBUS_TYPE_STRING, &session_name,
1739 DBUS_TYPE_STRING, &seat_name,
1741 return bus_send_error_reply(connection, message, &error, -EINVAL);
1743 session = hashmap_get(m->sessions, session_name);
1745 return bus_send_error_reply(connection, message, &error, -ENOENT);
1747 seat = hashmap_get(m->seats, seat_name);
1749 return bus_send_error_reply(connection, message, &error, -ENOENT);
1751 if (session->seat != seat)
1752 return bus_send_error_reply(connection, message, &error, -EINVAL);
1754 r = session_activate(session);
1756 return bus_send_error_reply(connection, message, NULL, r);
1758 reply = dbus_message_new_method_return(message);
1762 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSession") ||
1763 dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSession")) {
1767 if (!dbus_message_get_args(
1770 DBUS_TYPE_STRING, &name,
1772 return bus_send_error_reply(connection, message, &error, -EINVAL);
1774 session = hashmap_get(m->sessions, name);
1776 return bus_send_error_reply(connection, message, &error, -ENOENT);
1778 if (session_send_lock(session, streq(dbus_message_get_member(message), "LockSession")) < 0)
1781 reply = dbus_message_new_method_return(message);
1785 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions")) {
1789 HASHMAP_FOREACH(session, m->sessions, i)
1790 if (session_send_lock(session, true) < 0)
1793 reply = dbus_message_new_method_return(message);
1797 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillSession")) {
1804 if (!dbus_message_get_args(
1807 DBUS_TYPE_STRING, &name,
1808 DBUS_TYPE_STRING, &swho,
1809 DBUS_TYPE_INT32, &signo,
1811 return bus_send_error_reply(connection, message, &error, -EINVAL);
1816 who = kill_who_from_string(swho);
1818 return bus_send_error_reply(connection, message, &error, -EINVAL);
1821 if (signo <= 0 || signo >= _NSIG)
1822 return bus_send_error_reply(connection, message, &error, -EINVAL);
1824 session = hashmap_get(m->sessions, name);
1826 return bus_send_error_reply(connection, message, &error, -ENOENT);
1828 r = session_kill(session, who, signo);
1830 return bus_send_error_reply(connection, message, NULL, r);
1832 reply = dbus_message_new_method_return(message);
1836 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillUser")) {
1841 if (!dbus_message_get_args(
1844 DBUS_TYPE_UINT32, &uid,
1845 DBUS_TYPE_INT32, &signo,
1847 return bus_send_error_reply(connection, message, &error, -EINVAL);
1849 if (signo <= 0 || signo >= _NSIG)
1850 return bus_send_error_reply(connection, message, &error, -EINVAL);
1852 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1854 return bus_send_error_reply(connection, message, &error, -ENOENT);
1856 r = user_kill(user, signo);
1858 return bus_send_error_reply(connection, message, NULL, r);
1860 reply = dbus_message_new_method_return(message);
1864 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
1868 if (!dbus_message_get_args(
1871 DBUS_TYPE_STRING, &name,
1873 return bus_send_error_reply(connection, message, &error, -EINVAL);
1875 session = hashmap_get(m->sessions, name);
1877 return bus_send_error_reply(connection, message, &error, -ENOENT);
1879 r = session_stop(session);
1881 return bus_send_error_reply(connection, message, NULL, r);
1883 reply = dbus_message_new_method_return(message);
1887 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateUser")) {
1891 if (!dbus_message_get_args(
1894 DBUS_TYPE_UINT32, &uid,
1896 return bus_send_error_reply(connection, message, &error, -EINVAL);
1898 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1900 return bus_send_error_reply(connection, message, &error, -ENOENT);
1902 r = user_stop(user);
1904 return bus_send_error_reply(connection, message, NULL, r);
1906 reply = dbus_message_new_method_return(message);
1910 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSeat")) {
1914 if (!dbus_message_get_args(
1917 DBUS_TYPE_STRING, &name,
1919 return bus_send_error_reply(connection, message, &error, -EINVAL);
1921 seat = hashmap_get(m->seats, name);
1923 return bus_send_error_reply(connection, message, &error, -ENOENT);
1925 r = seat_stop_sessions(seat);
1927 return bus_send_error_reply(connection, message, NULL, r);
1929 reply = dbus_message_new_method_return(message);
1933 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "SetUserLinger")) {
1936 dbus_bool_t b, interactive;
1939 if (!dbus_message_get_args(
1942 DBUS_TYPE_UINT32, &uid,
1943 DBUS_TYPE_BOOLEAN, &b,
1944 DBUS_TYPE_BOOLEAN, &interactive,
1946 return bus_send_error_reply(connection, message, &error, -EINVAL);
1951 return bus_send_error_reply(connection, message, NULL, errno ? -errno : -EINVAL);
1953 r = verify_polkit(connection, message, "org.freedesktop.login1.set-user-linger", interactive, NULL, &error);
1955 return bus_send_error_reply(connection, message, &error, r);
1957 mkdir_p_label("/var/lib/systemd", 0755);
1959 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1961 return bus_send_error_reply(connection, message, &error, r);
1963 path = strappend("/var/lib/systemd/linger/", pw->pw_name);
1974 return bus_send_error_reply(connection, message, &error, r);
1976 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1985 if (r < 0 && errno != ENOENT)
1986 return bus_send_error_reply(connection, message, &error, -errno);
1988 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1990 user_add_to_gc_queue(u);
1993 reply = dbus_message_new_method_return(message);
1997 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "AttachDevice")) {
1998 const char *sysfs, *seat;
1999 dbus_bool_t interactive;
2001 if (!dbus_message_get_args(
2004 DBUS_TYPE_STRING, &seat,
2005 DBUS_TYPE_STRING, &sysfs,
2006 DBUS_TYPE_BOOLEAN, &interactive,
2008 return bus_send_error_reply(connection, message, &error, -EINVAL);
2010 if (!path_startswith(sysfs, "/sys") || !seat_name_is_valid(seat))
2011 return bus_send_error_reply(connection, message, NULL, -EINVAL);
2013 r = verify_polkit(connection, message, "org.freedesktop.login1.attach-device", interactive, NULL, &error);
2015 return bus_send_error_reply(connection, message, &error, r);
2017 r = attach_device(m, seat, sysfs);
2019 return bus_send_error_reply(connection, message, NULL, -EINVAL);
2021 reply = dbus_message_new_method_return(message);
2026 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "FlushDevices")) {
2027 dbus_bool_t interactive;
2029 if (!dbus_message_get_args(
2032 DBUS_TYPE_BOOLEAN, &interactive,
2034 return bus_send_error_reply(connection, message, &error, -EINVAL);
2036 r = verify_polkit(connection, message, "org.freedesktop.login1.flush-devices", interactive, NULL, &error);
2038 return bus_send_error_reply(connection, message, &error, r);
2040 r = flush_devices(m);
2042 return bus_send_error_reply(connection, message, NULL, -EINVAL);
2044 reply = dbus_message_new_method_return(message);
2048 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff")) {
2050 r = bus_manager_do_shutdown_or_sleep(
2051 m, connection, message,
2052 SPECIAL_POWEROFF_TARGET,
2054 "org.freedesktop.login1.power-off",
2055 "org.freedesktop.login1.power-off-multiple-sessions",
2056 "org.freedesktop.login1.power-off-ignore-inhibit",
2060 return bus_send_error_reply(connection, message, &error, r);
2061 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) {
2062 r = bus_manager_do_shutdown_or_sleep(
2063 m, connection, message,
2064 SPECIAL_REBOOT_TARGET,
2066 "org.freedesktop.login1.reboot",
2067 "org.freedesktop.login1.reboot-multiple-sessions",
2068 "org.freedesktop.login1.reboot-ignore-inhibit",
2072 return bus_send_error_reply(connection, message, &error, r);
2074 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Suspend")) {
2075 r = bus_manager_do_shutdown_or_sleep(
2076 m, connection, message,
2077 SPECIAL_SUSPEND_TARGET,
2079 "org.freedesktop.login1.suspend",
2080 "org.freedesktop.login1.suspend-multiple-sessions",
2081 "org.freedesktop.login1.suspend-ignore-inhibit",
2085 return bus_send_error_reply(connection, message, &error, r);
2086 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Hibernate")) {
2087 r = bus_manager_do_shutdown_or_sleep(
2088 m, connection, message,
2089 SPECIAL_HIBERNATE_TARGET,
2091 "org.freedesktop.login1.hibernate",
2092 "org.freedesktop.login1.hibernate-multiple-sessions",
2093 "org.freedesktop.login1.hibernate-ignore-inhibit",
2097 return bus_send_error_reply(connection, message, &error, r);
2099 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanPowerOff")) {
2101 r = bus_manager_can_shutdown_or_sleep(
2102 m, connection, message,
2104 "org.freedesktop.login1.power-off",
2105 "org.freedesktop.login1.power-off-multiple-sessions",
2106 "org.freedesktop.login1.power-off-ignore-inhibit",
2110 return bus_send_error_reply(connection, message, &error, r);
2111 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanReboot")) {
2112 r = bus_manager_can_shutdown_or_sleep(
2113 m, connection, message,
2115 "org.freedesktop.login1.reboot",
2116 "org.freedesktop.login1.reboot-multiple-sessions",
2117 "org.freedesktop.login1.reboot-ignore-inhibit",
2121 return bus_send_error_reply(connection, message, &error, r);
2123 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanSuspend")) {
2124 r = bus_manager_can_shutdown_or_sleep(
2125 m, connection, message,
2127 "org.freedesktop.login1.suspend",
2128 "org.freedesktop.login1.suspend-multiple-sessions",
2129 "org.freedesktop.login1.suspend-ignore-inhibit",
2133 return bus_send_error_reply(connection, message, &error, r);
2135 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHibernate")) {
2136 r = bus_manager_can_shutdown_or_sleep(
2137 m, connection, message,
2139 "org.freedesktop.login1.hibernate",
2140 "org.freedesktop.login1.hibernate-multiple-sessions",
2141 "org.freedesktop.login1.hibernate-ignore-inhibit",
2145 return bus_send_error_reply(connection, message, &error, r);
2147 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
2148 char *introspection = NULL;
2157 if (!(reply = dbus_message_new_method_return(message)))
2160 /* We roll our own introspection code here, instead of
2161 * relying on bus_default_message_handler() because we
2162 * need to generate our introspection string
2165 if (!(f = open_memstream(&introspection, &size)))
2168 fputs(INTROSPECTION_BEGIN, f);
2170 HASHMAP_FOREACH(seat, m->seats, i) {
2171 p = bus_path_escape(seat->id);
2174 fprintf(f, "<node name=\"seat/%s\"/>", p);
2179 HASHMAP_FOREACH(user, m->users, i)
2180 fprintf(f, "<node name=\"user/%llu\"/>", (unsigned long long) user->uid);
2182 HASHMAP_FOREACH(session, m->sessions, i) {
2183 p = bus_path_escape(session->id);
2186 fprintf(f, "<node name=\"session/%s\"/>", p);
2191 fputs(INTROSPECTION_END, f);
2195 free(introspection);
2204 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
2205 free(introspection);
2209 free(introspection);
2211 const BusBoundProperties bps[] = {
2212 { "org.freedesktop.login1.Manager", bus_login_manager_properties, m },
2215 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
2219 if (!dbus_connection_send(connection, reply, NULL))
2222 dbus_message_unref(reply);
2225 return DBUS_HANDLER_RESULT_HANDLED;
2229 dbus_message_unref(reply);
2231 dbus_error_free(&error);
2233 return DBUS_HANDLER_RESULT_NEED_MEMORY;
2236 const DBusObjectPathVTable bus_manager_vtable = {
2237 .message_function = manager_message_handler
2240 DBusHandlerResult bus_message_filter(
2241 DBusConnection *connection,
2242 DBusMessage *message,
2245 Manager *m = userdata;
2252 dbus_error_init(&error);
2254 if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
2257 if (!dbus_message_get_args(message, &error,
2258 DBUS_TYPE_STRING, &cgroup,
2260 log_error("Failed to parse Released message: %s", bus_error_message(&error));
2262 manager_cgroup_notify_empty(m, cgroup);
2265 dbus_error_free(&error);
2267 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2270 int manager_send_changed(Manager *manager, const char *properties) {
2276 m = bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties);
2280 if (!dbus_connection_send(manager->bus, m, NULL))
2287 dbus_message_unref(m);
2292 int manager_dispatch_delayed(Manager *manager) {
2293 const char *unit_name;
2300 if (!manager->delayed_unit)
2303 /* Continue delay? */
2305 manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
2306 manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL, false);
2310 bus_manager_log_shutdown(manager, manager->delayed_what, manager->delayed_unit);
2312 /* Reset delay data */
2313 unit_name = manager->delayed_unit;
2314 manager->delayed_unit = NULL;
2316 /* Actually do the shutdown */
2317 dbus_error_init(&error);
2318 r = send_start_unit(manager->bus, unit_name, &error);
2320 log_warning("Failed to send delayed message: %s", bus_error_message_or_strerror(&error, -r));
2321 dbus_error_free(&error);
2325 /* Tell people about it */
2326 send_prepare_for(manager, manager->delayed_what, false);