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(
967 /* Check for other users' sessions. Greeter sessions do not count. */
968 HASHMAP_FOREACH(session, m->sessions, i)
969 if (session->class == SESSION_USER && session->user->uid != uid)
975 static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) {
976 const char *mode = "replace";
980 return bus_method_call_with_reply (
982 "org.freedesktop.systemd1",
983 "/org/freedesktop/systemd1",
984 "org.freedesktop.systemd1.Manager",
988 DBUS_TYPE_STRING, &unit_name,
989 DBUS_TYPE_STRING, &mode,
993 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
994 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
995 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
996 [INHIBIT_SLEEP] = "PrepareForSleep"
999 dbus_bool_t active = _active;
1000 DBusMessage *message;
1005 assert(w < _INHIBIT_WHAT_MAX);
1006 assert(signal_name[w]);
1008 message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]);
1012 if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID) ||
1013 !dbus_connection_send(m->bus, message, NULL))
1016 dbus_message_unref(message);
1020 static int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, const char *unit_name) {
1023 assert(w < _INHIBIT_WHAT_MAX);
1025 /* Tell everybody to prepare for shutdown/sleep */
1026 send_prepare_for(m, w, true);
1028 /* Update timestamp for timeout */
1029 if (!m->delayed_unit)
1030 m->delayed_timestamp = now(CLOCK_MONOTONIC);
1032 /* Remember what we want to do, possibly overriding what kind
1033 * of unit we previously queued. */
1034 m->delayed_unit = unit_name;
1035 m->delayed_what = w;
1040 static int bus_manager_can_shutdown_or_sleep(
1042 DBusConnection *connection,
1043 DBusMessage *message,
1046 const char *action_multiple_sessions,
1047 const char *action_ignore_inhibit,
1048 const char *sleep_type,
1050 DBusMessage **_reply) {
1052 bool multiple_sessions, challenge, blocked, b;
1054 DBusMessage *reply = NULL;
1062 assert(w <= _INHIBIT_WHAT_MAX);
1064 assert(action_multiple_sessions);
1065 assert(action_ignore_inhibit);
1070 r = can_sleep(sleep_type);
1080 ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
1081 if (ul == (unsigned long) -1)
1084 r = have_multiple_sessions(m, (uid_t) ul);
1088 multiple_sessions = r > 0;
1089 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, (uid_t) ul);
1091 if (multiple_sessions) {
1092 r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
1099 result = "challenge";
1105 r = verify_polkit(connection, message, action_ignore_inhibit, false, &challenge, error);
1109 if (r > 0 && !result)
1111 else if (challenge && (!result || streq(result, "yes")))
1112 result = "challenge";
1117 if (!multiple_sessions && !blocked) {
1118 /* If neither inhibit nor multiple sessions
1119 * apply then just check the normal policy */
1121 r = verify_polkit(connection, message, action, false, &challenge, error);
1128 result = "challenge";
1134 reply = dbus_message_new_method_return(message);
1138 b = dbus_message_append_args(
1140 DBUS_TYPE_STRING, &result,
1143 dbus_message_unref(reply);
1151 static int bus_manager_log_shutdown(
1154 const char *unit_name) {
1161 if (w != INHIBIT_SHUTDOWN)
1164 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1165 p = "MESSAGE=System is powering down.";
1166 q = "SHUTDOWN=power-off";
1167 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1168 p = "MESSAGE=System is halting.";
1169 q = "SHUTDOWN=halt";
1170 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1171 p = "MESSAGE=System is rebooting.";
1172 q = "SHUTDOWN=reboot";
1173 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1174 p = "MESSAGE=System is rebooting with kexec.";
1175 q = "SHUTDOWN=kexec";
1177 p = "MESSAGE=System is shutting down.";
1181 return log_struct(LOG_NOTICE,
1182 "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(SD_MESSAGE_SHUTDOWN),
1187 int bus_manager_shutdown_or_sleep_now_or_later(
1189 const char *unit_name,
1199 assert(w <= _INHIBIT_WHAT_MAX);
1202 m->inhibit_delay_max > 0 &&
1203 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0);
1206 /* Shutdown is delayed, keep in mind what we
1207 * want to do, and start a timeout */
1208 r = delay_shutdown_or_sleep(m, w, unit_name);
1210 bus_manager_log_shutdown(m, w, unit_name);
1212 /* Shutdown is not delayed, execute it
1214 r = send_start_unit(m->bus, unit_name, error);
1220 static int bus_manager_do_shutdown_or_sleep(
1222 DBusConnection *connection,
1223 DBusMessage *message,
1224 const char *unit_name,
1227 const char *action_multiple_sessions,
1228 const char *action_ignore_inhibit,
1229 const char *sleep_type,
1231 DBusMessage **_reply) {
1233 dbus_bool_t interactive;
1234 bool multiple_sessions, blocked;
1235 DBusMessage *reply = NULL;
1244 assert(w <= _INHIBIT_WHAT_MAX);
1246 assert(action_multiple_sessions);
1247 assert(action_ignore_inhibit);
1251 if (!dbus_message_get_args(
1254 DBUS_TYPE_BOOLEAN, &interactive,
1259 r = can_sleep(sleep_type);
1267 ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
1268 if (ul == (unsigned long) -1)
1271 r = have_multiple_sessions(m, (uid_t) ul);
1275 multiple_sessions = r > 0;
1276 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, (uid_t) ul);
1278 if (multiple_sessions) {
1279 r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
1285 r = verify_polkit(connection, message, action_ignore_inhibit, interactive, NULL, error);
1290 if (!multiple_sessions && !blocked) {
1291 r = verify_polkit(connection, message, action, interactive, NULL, error);
1296 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1300 reply = dbus_message_new_method_return(message);
1308 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_button, handle_button, HandleButton);
1310 static const BusProperty bus_login_manager_properties[] = {
1311 { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_path), true },
1312 { "Controllers", bus_property_append_strv, "as", offsetof(Manager, controllers), true },
1313 { "ResetControllers", bus_property_append_strv, "as", offsetof(Manager, reset_controllers), true },
1314 { "NAutoVTs", bus_property_append_unsigned, "u", offsetof(Manager, n_autovts) },
1315 { "KillOnlyUsers", bus_property_append_strv, "as", offsetof(Manager, kill_only_users), true },
1316 { "KillExcludeUsers", bus_property_append_strv, "as", offsetof(Manager, kill_exclude_users), true },
1317 { "KillUserProcesses", bus_property_append_bool, "b", offsetof(Manager, kill_user_processes) },
1318 { "IdleHint", bus_manager_append_idle_hint, "b", 0 },
1319 { "IdleSinceHint", bus_manager_append_idle_hint_since, "t", 0 },
1320 { "IdleSinceHintMonotonic", bus_manager_append_idle_hint_since, "t", 0 },
1321 { "BlockInhibited", bus_manager_append_inhibited, "s", 0 },
1322 { "DelayInhibited", bus_manager_append_inhibited, "s", 0 },
1323 { "InhibitDelayMaxUSec", bus_property_append_usec, "t", offsetof(Manager, inhibit_delay_max) },
1324 { "HandlePowerKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_power_key) },
1325 { "HandleSleepKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_sleep_key) },
1326 { "HandleLidSwitch", bus_manager_append_handle_button, "s", offsetof(Manager, handle_lid_switch) },
1327 { "PreparingForShutdown", bus_manager_append_preparing, "b", 0 },
1328 { "PreparingForSleep", bus_manager_append_preparing, "b", 0 },
1332 static DBusHandlerResult manager_message_handler(
1333 DBusConnection *connection,
1334 DBusMessage *message,
1337 Manager *m = userdata;
1340 DBusMessage *reply = NULL;
1347 dbus_error_init(&error);
1349 if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSession")) {
1355 if (!dbus_message_get_args(
1358 DBUS_TYPE_STRING, &name,
1360 return bus_send_error_reply(connection, message, &error, -EINVAL);
1362 session = hashmap_get(m->sessions, name);
1364 return bus_send_error_reply(connection, message, &error, -ENOENT);
1366 reply = dbus_message_new_method_return(message);
1370 p = session_bus_path(session);
1374 b = dbus_message_append_args(
1376 DBUS_TYPE_OBJECT_PATH, &p,
1383 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSessionByPID")) {
1389 if (!dbus_message_get_args(
1392 DBUS_TYPE_UINT32, &pid,
1394 return bus_send_error_reply(connection, message, &error, -EINVAL);
1396 r = manager_get_session_by_pid(m, pid, &session);
1398 return bus_send_error_reply(connection, message, NULL, r < 0 ? r : -ENOENT);
1400 reply = dbus_message_new_method_return(message);
1404 p = session_bus_path(session);
1408 b = dbus_message_append_args(
1410 DBUS_TYPE_OBJECT_PATH, &p,
1417 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetUser")) {
1423 if (!dbus_message_get_args(
1426 DBUS_TYPE_UINT32, &uid,
1428 return bus_send_error_reply(connection, message, &error, -EINVAL);
1430 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1432 return bus_send_error_reply(connection, message, &error, -ENOENT);
1434 reply = dbus_message_new_method_return(message);
1438 p = user_bus_path(user);
1442 b = dbus_message_append_args(
1444 DBUS_TYPE_OBJECT_PATH, &p,
1451 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSeat")) {
1457 if (!dbus_message_get_args(
1460 DBUS_TYPE_STRING, &name,
1462 return bus_send_error_reply(connection, message, &error, -EINVAL);
1464 seat = hashmap_get(m->seats, name);
1466 return bus_send_error_reply(connection, message, &error, -ENOENT);
1468 reply = dbus_message_new_method_return(message);
1472 p = seat_bus_path(seat);
1476 b = dbus_message_append_args(
1478 DBUS_TYPE_OBJECT_PATH, &p,
1485 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSessions")) {
1489 DBusMessageIter iter, sub;
1490 const char *empty = "";
1492 reply = dbus_message_new_method_return(message);
1496 dbus_message_iter_init_append(reply, &iter);
1498 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(susso)", &sub))
1501 HASHMAP_FOREACH(session, m->sessions, i) {
1502 DBusMessageIter sub2;
1505 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1508 uid = session->user->uid;
1510 p = session_bus_path(session);
1514 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
1515 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
1516 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->user->name) ||
1517 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, session->seat ? (const char**) &session->seat->id : &empty) ||
1518 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
1525 if (!dbus_message_iter_close_container(&sub, &sub2))
1529 if (!dbus_message_iter_close_container(&iter, &sub))
1532 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListUsers")) {
1536 DBusMessageIter iter, sub;
1538 reply = dbus_message_new_method_return(message);
1542 dbus_message_iter_init_append(reply, &iter);
1544 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(uso)", &sub))
1547 HASHMAP_FOREACH(user, m->users, i) {
1548 DBusMessageIter sub2;
1551 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1556 p = user_bus_path(user);
1560 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
1561 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &user->name) ||
1562 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
1569 if (!dbus_message_iter_close_container(&sub, &sub2))
1573 if (!dbus_message_iter_close_container(&iter, &sub))
1576 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSeats")) {
1580 DBusMessageIter iter, sub;
1582 reply = dbus_message_new_method_return(message);
1586 dbus_message_iter_init_append(reply, &iter);
1588 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(so)", &sub))
1591 HASHMAP_FOREACH(seat, m->seats, i) {
1592 DBusMessageIter sub2;
1594 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1597 p = seat_bus_path(seat);
1601 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &seat->id) ||
1602 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
1609 if (!dbus_message_iter_close_container(&sub, &sub2))
1613 if (!dbus_message_iter_close_container(&iter, &sub))
1616 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListInhibitors")) {
1617 Inhibitor *inhibitor;
1619 DBusMessageIter iter, sub;
1621 reply = dbus_message_new_method_return(message);
1625 dbus_message_iter_init_append(reply, &iter);
1627 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssuu)", &sub))
1630 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
1631 DBusMessageIter sub2;
1632 dbus_uint32_t uid, pid;
1633 const char *what, *who, *why, *mode;
1635 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
1638 what = strempty(inhibit_what_to_string(inhibitor->what));
1639 who = strempty(inhibitor->who);
1640 why = strempty(inhibitor->why);
1641 mode = strempty(inhibit_mode_to_string(inhibitor->mode));
1642 uid = (dbus_uint32_t) inhibitor->uid;
1643 pid = (dbus_uint32_t) inhibitor->pid;
1645 if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &what) ||
1646 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &who) ||
1647 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &why) ||
1648 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &mode) ||
1649 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
1650 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid))
1653 if (!dbus_message_iter_close_container(&sub, &sub2))
1657 if (!dbus_message_iter_close_container(&iter, &sub))
1660 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Inhibit")) {
1662 r = bus_manager_inhibit(m, connection, message, &error, &reply);
1665 return bus_send_error_reply(connection, message, &error, r);
1668 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CreateSession")) {
1670 r = bus_manager_create_session(m, message, &reply);
1672 /* Don't delay the work on OOM here, since it might be
1673 * triggered by a low RLIMIT_NOFILE here (since we
1674 * send a dupped fd to the client), and we'd rather
1675 * see this fail quickly then be retried later */
1678 return bus_send_error_reply(connection, message, NULL, r);
1680 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ReleaseSession")) {
1684 if (!dbus_message_get_args(
1687 DBUS_TYPE_STRING, &name,
1689 return bus_send_error_reply(connection, message, &error, -EINVAL);
1691 session = hashmap_get(m->sessions, name);
1693 return bus_send_error_reply(connection, message, &error, -ENOENT);
1695 /* We use the FIFO to detect stray sessions where the
1696 process invoking PAM dies abnormally. We need to make
1697 sure that that process is not killed if at the clean
1698 end of the session it closes the FIFO. Hence, with
1699 this call explicitly turn off the FIFO logic, so that
1700 the PAM code can finish clean up on its own */
1701 session_remove_fifo(session);
1703 reply = dbus_message_new_method_return(message);
1707 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSession")) {
1711 if (!dbus_message_get_args(
1714 DBUS_TYPE_STRING, &name,
1716 return bus_send_error_reply(connection, message, &error, -EINVAL);
1718 session = hashmap_get(m->sessions, name);
1720 return bus_send_error_reply(connection, message, &error, -ENOENT);
1722 r = session_activate(session);
1724 return bus_send_error_reply(connection, message, NULL, r);
1726 reply = dbus_message_new_method_return(message);
1730 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSessionOnSeat")) {
1731 const char *session_name, *seat_name;
1735 /* Same as ActivateSession() but refuses to work if
1736 * the seat doesn't match */
1738 if (!dbus_message_get_args(
1741 DBUS_TYPE_STRING, &session_name,
1742 DBUS_TYPE_STRING, &seat_name,
1744 return bus_send_error_reply(connection, message, &error, -EINVAL);
1746 session = hashmap_get(m->sessions, session_name);
1748 return bus_send_error_reply(connection, message, &error, -ENOENT);
1750 seat = hashmap_get(m->seats, seat_name);
1752 return bus_send_error_reply(connection, message, &error, -ENOENT);
1754 if (session->seat != seat)
1755 return bus_send_error_reply(connection, message, &error, -EINVAL);
1757 r = session_activate(session);
1759 return bus_send_error_reply(connection, message, NULL, r);
1761 reply = dbus_message_new_method_return(message);
1765 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSession") ||
1766 dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSession")) {
1770 if (!dbus_message_get_args(
1773 DBUS_TYPE_STRING, &name,
1775 return bus_send_error_reply(connection, message, &error, -EINVAL);
1777 session = hashmap_get(m->sessions, name);
1779 return bus_send_error_reply(connection, message, &error, -ENOENT);
1781 if (session_send_lock(session, streq(dbus_message_get_member(message), "LockSession")) < 0)
1784 reply = dbus_message_new_method_return(message);
1788 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions")) {
1792 HASHMAP_FOREACH(session, m->sessions, i)
1793 if (session_send_lock(session, true) < 0)
1796 reply = dbus_message_new_method_return(message);
1800 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillSession")) {
1807 if (!dbus_message_get_args(
1810 DBUS_TYPE_STRING, &name,
1811 DBUS_TYPE_STRING, &swho,
1812 DBUS_TYPE_INT32, &signo,
1814 return bus_send_error_reply(connection, message, &error, -EINVAL);
1819 who = kill_who_from_string(swho);
1821 return bus_send_error_reply(connection, message, &error, -EINVAL);
1824 if (signo <= 0 || signo >= _NSIG)
1825 return bus_send_error_reply(connection, message, &error, -EINVAL);
1827 session = hashmap_get(m->sessions, name);
1829 return bus_send_error_reply(connection, message, &error, -ENOENT);
1831 r = session_kill(session, who, signo);
1833 return bus_send_error_reply(connection, message, NULL, r);
1835 reply = dbus_message_new_method_return(message);
1839 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillUser")) {
1844 if (!dbus_message_get_args(
1847 DBUS_TYPE_UINT32, &uid,
1848 DBUS_TYPE_INT32, &signo,
1850 return bus_send_error_reply(connection, message, &error, -EINVAL);
1852 if (signo <= 0 || signo >= _NSIG)
1853 return bus_send_error_reply(connection, message, &error, -EINVAL);
1855 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1857 return bus_send_error_reply(connection, message, &error, -ENOENT);
1859 r = user_kill(user, signo);
1861 return bus_send_error_reply(connection, message, NULL, r);
1863 reply = dbus_message_new_method_return(message);
1867 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
1871 if (!dbus_message_get_args(
1874 DBUS_TYPE_STRING, &name,
1876 return bus_send_error_reply(connection, message, &error, -EINVAL);
1878 session = hashmap_get(m->sessions, name);
1880 return bus_send_error_reply(connection, message, &error, -ENOENT);
1882 r = session_stop(session);
1884 return bus_send_error_reply(connection, message, NULL, r);
1886 reply = dbus_message_new_method_return(message);
1890 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateUser")) {
1894 if (!dbus_message_get_args(
1897 DBUS_TYPE_UINT32, &uid,
1899 return bus_send_error_reply(connection, message, &error, -EINVAL);
1901 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1903 return bus_send_error_reply(connection, message, &error, -ENOENT);
1905 r = user_stop(user);
1907 return bus_send_error_reply(connection, message, NULL, r);
1909 reply = dbus_message_new_method_return(message);
1913 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSeat")) {
1917 if (!dbus_message_get_args(
1920 DBUS_TYPE_STRING, &name,
1922 return bus_send_error_reply(connection, message, &error, -EINVAL);
1924 seat = hashmap_get(m->seats, name);
1926 return bus_send_error_reply(connection, message, &error, -ENOENT);
1928 r = seat_stop_sessions(seat);
1930 return bus_send_error_reply(connection, message, NULL, r);
1932 reply = dbus_message_new_method_return(message);
1936 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "SetUserLinger")) {
1939 dbus_bool_t b, interactive;
1942 if (!dbus_message_get_args(
1945 DBUS_TYPE_UINT32, &uid,
1946 DBUS_TYPE_BOOLEAN, &b,
1947 DBUS_TYPE_BOOLEAN, &interactive,
1949 return bus_send_error_reply(connection, message, &error, -EINVAL);
1954 return bus_send_error_reply(connection, message, NULL, errno ? -errno : -EINVAL);
1956 r = verify_polkit(connection, message, "org.freedesktop.login1.set-user-linger", interactive, NULL, &error);
1958 return bus_send_error_reply(connection, message, &error, r);
1960 mkdir_p_label("/var/lib/systemd", 0755);
1962 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1964 return bus_send_error_reply(connection, message, &error, r);
1966 path = strappend("/var/lib/systemd/linger/", pw->pw_name);
1977 return bus_send_error_reply(connection, message, &error, r);
1979 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1988 if (r < 0 && errno != ENOENT)
1989 return bus_send_error_reply(connection, message, &error, -errno);
1991 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1993 user_add_to_gc_queue(u);
1996 reply = dbus_message_new_method_return(message);
2000 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "AttachDevice")) {
2001 const char *sysfs, *seat;
2002 dbus_bool_t interactive;
2004 if (!dbus_message_get_args(
2007 DBUS_TYPE_STRING, &seat,
2008 DBUS_TYPE_STRING, &sysfs,
2009 DBUS_TYPE_BOOLEAN, &interactive,
2011 return bus_send_error_reply(connection, message, &error, -EINVAL);
2013 if (!path_startswith(sysfs, "/sys") || !seat_name_is_valid(seat))
2014 return bus_send_error_reply(connection, message, NULL, -EINVAL);
2016 r = verify_polkit(connection, message, "org.freedesktop.login1.attach-device", interactive, NULL, &error);
2018 return bus_send_error_reply(connection, message, &error, r);
2020 r = attach_device(m, seat, sysfs);
2022 return bus_send_error_reply(connection, message, NULL, -EINVAL);
2024 reply = dbus_message_new_method_return(message);
2029 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "FlushDevices")) {
2030 dbus_bool_t interactive;
2032 if (!dbus_message_get_args(
2035 DBUS_TYPE_BOOLEAN, &interactive,
2037 return bus_send_error_reply(connection, message, &error, -EINVAL);
2039 r = verify_polkit(connection, message, "org.freedesktop.login1.flush-devices", interactive, NULL, &error);
2041 return bus_send_error_reply(connection, message, &error, r);
2043 r = flush_devices(m);
2045 return bus_send_error_reply(connection, message, NULL, -EINVAL);
2047 reply = dbus_message_new_method_return(message);
2051 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff")) {
2053 r = bus_manager_do_shutdown_or_sleep(
2054 m, connection, message,
2055 SPECIAL_POWEROFF_TARGET,
2057 "org.freedesktop.login1.power-off",
2058 "org.freedesktop.login1.power-off-multiple-sessions",
2059 "org.freedesktop.login1.power-off-ignore-inhibit",
2063 return bus_send_error_reply(connection, message, &error, r);
2064 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) {
2065 r = bus_manager_do_shutdown_or_sleep(
2066 m, connection, message,
2067 SPECIAL_REBOOT_TARGET,
2069 "org.freedesktop.login1.reboot",
2070 "org.freedesktop.login1.reboot-multiple-sessions",
2071 "org.freedesktop.login1.reboot-ignore-inhibit",
2075 return bus_send_error_reply(connection, message, &error, r);
2077 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Suspend")) {
2078 r = bus_manager_do_shutdown_or_sleep(
2079 m, connection, message,
2080 SPECIAL_SUSPEND_TARGET,
2082 "org.freedesktop.login1.suspend",
2083 "org.freedesktop.login1.suspend-multiple-sessions",
2084 "org.freedesktop.login1.suspend-ignore-inhibit",
2088 return bus_send_error_reply(connection, message, &error, r);
2089 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Hibernate")) {
2090 r = bus_manager_do_shutdown_or_sleep(
2091 m, connection, message,
2092 SPECIAL_HIBERNATE_TARGET,
2094 "org.freedesktop.login1.hibernate",
2095 "org.freedesktop.login1.hibernate-multiple-sessions",
2096 "org.freedesktop.login1.hibernate-ignore-inhibit",
2100 return bus_send_error_reply(connection, message, &error, r);
2102 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanPowerOff")) {
2104 r = bus_manager_can_shutdown_or_sleep(
2105 m, connection, message,
2107 "org.freedesktop.login1.power-off",
2108 "org.freedesktop.login1.power-off-multiple-sessions",
2109 "org.freedesktop.login1.power-off-ignore-inhibit",
2113 return bus_send_error_reply(connection, message, &error, r);
2114 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanReboot")) {
2115 r = bus_manager_can_shutdown_or_sleep(
2116 m, connection, message,
2118 "org.freedesktop.login1.reboot",
2119 "org.freedesktop.login1.reboot-multiple-sessions",
2120 "org.freedesktop.login1.reboot-ignore-inhibit",
2124 return bus_send_error_reply(connection, message, &error, r);
2126 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanSuspend")) {
2127 r = bus_manager_can_shutdown_or_sleep(
2128 m, connection, message,
2130 "org.freedesktop.login1.suspend",
2131 "org.freedesktop.login1.suspend-multiple-sessions",
2132 "org.freedesktop.login1.suspend-ignore-inhibit",
2136 return bus_send_error_reply(connection, message, &error, r);
2138 } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHibernate")) {
2139 r = bus_manager_can_shutdown_or_sleep(
2140 m, connection, message,
2142 "org.freedesktop.login1.hibernate",
2143 "org.freedesktop.login1.hibernate-multiple-sessions",
2144 "org.freedesktop.login1.hibernate-ignore-inhibit",
2148 return bus_send_error_reply(connection, message, &error, r);
2150 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
2151 char *introspection = NULL;
2160 if (!(reply = dbus_message_new_method_return(message)))
2163 /* We roll our own introspection code here, instead of
2164 * relying on bus_default_message_handler() because we
2165 * need to generate our introspection string
2168 if (!(f = open_memstream(&introspection, &size)))
2171 fputs(INTROSPECTION_BEGIN, f);
2173 HASHMAP_FOREACH(seat, m->seats, i) {
2174 p = bus_path_escape(seat->id);
2177 fprintf(f, "<node name=\"seat/%s\"/>", p);
2182 HASHMAP_FOREACH(user, m->users, i)
2183 fprintf(f, "<node name=\"user/%llu\"/>", (unsigned long long) user->uid);
2185 HASHMAP_FOREACH(session, m->sessions, i) {
2186 p = bus_path_escape(session->id);
2189 fprintf(f, "<node name=\"session/%s\"/>", p);
2194 fputs(INTROSPECTION_END, f);
2198 free(introspection);
2207 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
2208 free(introspection);
2212 free(introspection);
2214 const BusBoundProperties bps[] = {
2215 { "org.freedesktop.login1.Manager", bus_login_manager_properties, m },
2218 return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
2222 if (!dbus_connection_send(connection, reply, NULL))
2225 dbus_message_unref(reply);
2228 return DBUS_HANDLER_RESULT_HANDLED;
2232 dbus_message_unref(reply);
2234 dbus_error_free(&error);
2236 return DBUS_HANDLER_RESULT_NEED_MEMORY;
2239 const DBusObjectPathVTable bus_manager_vtable = {
2240 .message_function = manager_message_handler
2243 DBusHandlerResult bus_message_filter(
2244 DBusConnection *connection,
2245 DBusMessage *message,
2248 Manager *m = userdata;
2255 dbus_error_init(&error);
2257 if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
2260 if (!dbus_message_get_args(message, &error,
2261 DBUS_TYPE_STRING, &cgroup,
2263 log_error("Failed to parse Released message: %s", bus_error_message(&error));
2265 manager_cgroup_notify_empty(m, cgroup);
2268 dbus_error_free(&error);
2270 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2273 int manager_send_changed(Manager *manager, const char *properties) {
2279 m = bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties);
2283 if (!dbus_connection_send(manager->bus, m, NULL))
2290 dbus_message_unref(m);
2295 int manager_dispatch_delayed(Manager *manager) {
2296 const char *unit_name;
2303 if (!manager->delayed_unit)
2306 /* Continue delay? */
2308 manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
2309 manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL, false, false, 0);
2313 bus_manager_log_shutdown(manager, manager->delayed_what, manager->delayed_unit);
2315 /* Reset delay data */
2316 unit_name = manager->delayed_unit;
2317 manager->delayed_unit = NULL;
2319 /* Actually do the shutdown */
2320 dbus_error_init(&error);
2321 r = send_start_unit(manager->bus, unit_name, &error);
2323 log_warning("Failed to send delayed message: %s", bus_error_message_or_strerror(&error, -r));
2324 dbus_error_free(&error);
2328 /* Tell people about it */
2329 send_prepare_for(manager, manager->delayed_what, false);