1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "sd-messages.h"
28 #include "alloc-util.h"
29 #include "audit-util.h"
30 #include "bus-common-errors.h"
31 #include "bus-error.h"
33 #include "dirent-util.h"
34 //#include "efivars.h"
37 #include "fileio-label.h"
38 #include "format-util.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 //#include "cgroup-util.h"
45 #include "selinux-util.h"
46 #include "sleep-config.h"
47 //#include "special.h"
49 #include "terminal-util.h"
50 #include "udev-util.h"
51 #include "unit-name.h"
52 #include "user-util.h"
53 #include "utmp-wtmp.h"
55 /// Additional includes needed by elogind
56 #include "elogind-dbus.h"
58 static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
60 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
65 /* Get client login session. This is not what you are looking for these days,
66 * as apps may instead belong to a user service unit. This includes terminal
67 * emulators and hence command-line apps. */
68 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
72 r = sd_bus_creds_get_session(creds, &name);
78 session = hashmap_get(m->sessions, name);
86 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
87 "Caller does not belong to any known session");
90 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
98 return get_sender_session(m, message, error, ret);
100 session = hashmap_get(m->sessions, name);
102 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
108 static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
110 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
115 /* Note that we get the owner UID of the session, not the actual client UID here! */
116 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
120 r = sd_bus_creds_get_owner_uid(creds, &uid);
126 user = hashmap_get(m->users, UID_TO_PTR(uid));
134 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "Caller does not belong to any logged in user or lingering user");
137 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
144 if (!uid_is_valid(uid))
145 return get_sender_user(m, message, error, ret);
147 user = hashmap_get(m->users, UID_TO_PTR(uid));
149 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "User ID "UID_FMT" is not logged in or lingering", uid);
155 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
166 r = manager_get_session_from_creds(m, message, NULL, error, &session);
170 seat = session->seat;
172 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
174 seat = hashmap_get(m->seats, name);
176 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
183 static int property_get_idle_hint(
186 const char *interface,
187 const char *property,
188 sd_bus_message *reply,
190 sd_bus_error *error) {
192 Manager *m = userdata;
198 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
201 static int property_get_idle_since_hint(
204 const char *interface,
205 const char *property,
206 sd_bus_message *reply,
208 sd_bus_error *error) {
210 Manager *m = userdata;
211 dual_timestamp t = DUAL_TIMESTAMP_NULL;
217 manager_get_idle_hint(m, &t);
219 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
222 static int property_get_inhibited(
225 const char *interface,
226 const char *property,
227 sd_bus_message *reply,
229 sd_bus_error *error) {
231 Manager *m = userdata;
238 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
240 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
243 static int property_get_preparing(
246 const char *interface,
247 const char *property,
248 sd_bus_message *reply,
250 sd_bus_error *error) {
252 Manager *m = userdata;
259 if (streq(property, "PreparingForShutdown"))
260 b = !!(m->action_what & INHIBIT_SHUTDOWN);
262 b = !!(m->action_what & INHIBIT_SLEEP);
264 return sd_bus_message_append(reply, "b", b);
267 static int property_get_scheduled_shutdown(
270 const char *interface,
271 const char *property,
272 sd_bus_message *reply,
274 sd_bus_error *error) {
276 Manager *m = userdata;
283 r = sd_bus_message_open_container(reply, 'r', "st");
287 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
291 return sd_bus_message_close_container(reply);
294 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
296 static int property_get_docked(
299 const char *interface,
300 const char *property,
301 sd_bus_message *reply,
303 sd_bus_error *error) {
305 Manager *m = userdata;
311 return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
314 static int property_get_current_sessions(
317 const char *interface,
318 const char *property,
319 sd_bus_message *reply,
321 sd_bus_error *error) {
323 Manager *m = userdata;
329 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
332 static int property_get_current_inhibitors(
335 const char *interface,
336 const char *property,
337 sd_bus_message *reply,
339 sd_bus_error *error) {
341 Manager *m = userdata;
347 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
350 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
351 _cleanup_free_ char *p = NULL;
352 Manager *m = userdata;
360 r = sd_bus_message_read(message, "s", &name);
364 r = manager_get_session_from_creds(m, message, name, error, &session);
368 p = session_bus_path(session);
372 return sd_bus_reply_method_return(message, "o", p);
375 /* Get login session of a process. This is not what you are looking for these days,
376 * as apps may instead belong to a user service unit. This includes terminal
377 * emulators and hence command-line apps. */
378 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
379 _cleanup_free_ char *p = NULL;
380 Session *session = NULL;
381 Manager *m = userdata;
388 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
390 r = sd_bus_message_read(message, "u", &pid);
397 r = manager_get_session_from_creds(m, message, NULL, error, &session);
401 r = manager_get_session_by_pid(m, pid, &session);
406 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
409 p = session_bus_path(session);
413 return sd_bus_reply_method_return(message, "o", p);
416 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
417 _cleanup_free_ char *p = NULL;
418 Manager *m = userdata;
426 r = sd_bus_message_read(message, "u", &uid);
430 r = manager_get_user_from_creds(m, message, uid, error, &user);
434 p = user_bus_path(user);
438 return sd_bus_reply_method_return(message, "o", p);
441 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
442 _cleanup_free_ char *p = NULL;
443 Manager *m = userdata;
451 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
453 r = sd_bus_message_read(message, "u", &pid);
460 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
464 r = manager_get_user_by_pid(m, pid, &user);
468 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
469 "PID "PID_FMT" does not belong to any logged in user or lingering user",
473 p = user_bus_path(user);
477 return sd_bus_reply_method_return(message, "o", p);
480 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
481 _cleanup_free_ char *p = NULL;
482 Manager *m = userdata;
490 r = sd_bus_message_read(message, "s", &name);
494 r = manager_get_seat_from_creds(m, message, name, error, &seat);
498 p = seat_bus_path(seat);
502 return sd_bus_reply_method_return(message, "o", p);
505 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
506 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
507 Manager *m = userdata;
515 r = sd_bus_message_new_method_return(message, &reply);
519 r = sd_bus_message_open_container(reply, 'a', "(susso)");
523 HASHMAP_FOREACH(session, m->sessions, i) {
524 _cleanup_free_ char *p = NULL;
526 p = session_bus_path(session);
530 r = sd_bus_message_append(reply, "(susso)",
532 (uint32_t) session->user->uid,
534 session->seat ? session->seat->id : "",
540 r = sd_bus_message_close_container(reply);
544 return sd_bus_send(NULL, reply, NULL);
547 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
548 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
549 Manager *m = userdata;
557 r = sd_bus_message_new_method_return(message, &reply);
561 r = sd_bus_message_open_container(reply, 'a', "(uso)");
565 HASHMAP_FOREACH(user, m->users, i) {
566 _cleanup_free_ char *p = NULL;
568 p = user_bus_path(user);
572 r = sd_bus_message_append(reply, "(uso)",
573 (uint32_t) user->uid,
580 r = sd_bus_message_close_container(reply);
584 return sd_bus_send(NULL, reply, NULL);
587 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
588 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
589 Manager *m = userdata;
597 r = sd_bus_message_new_method_return(message, &reply);
601 r = sd_bus_message_open_container(reply, 'a', "(so)");
605 HASHMAP_FOREACH(seat, m->seats, i) {
606 _cleanup_free_ char *p = NULL;
608 p = seat_bus_path(seat);
612 r = sd_bus_message_append(reply, "(so)", seat->id, p);
617 r = sd_bus_message_close_container(reply);
621 return sd_bus_send(NULL, reply, NULL);
624 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
625 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
626 Manager *m = userdata;
627 Inhibitor *inhibitor;
634 r = sd_bus_message_new_method_return(message, &reply);
638 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
642 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
644 r = sd_bus_message_append(reply, "(ssssuu)",
645 strempty(inhibit_what_to_string(inhibitor->what)),
646 strempty(inhibitor->who),
647 strempty(inhibitor->why),
648 strempty(inhibit_mode_to_string(inhibitor->mode)),
649 (uint32_t) inhibitor->uid,
650 (uint32_t) inhibitor->pid);
655 r = sd_bus_message_close_container(reply);
659 return sd_bus_send(NULL, reply, NULL);
662 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
663 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
664 _cleanup_free_ char *unit = NULL, *id = NULL;
665 Session *session = NULL;
666 uint32_t audit_id = 0;
667 Manager *m = userdata;
681 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
682 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
684 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
688 if (!uid_is_valid(uid))
689 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
690 if (leader < 0 || leader == 1 || leader == getpid_cached())
691 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
694 t = _SESSION_TYPE_INVALID;
696 t = session_type_from_string(type);
698 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
702 c = _SESSION_CLASS_INVALID;
704 c = session_class_from_string(class);
706 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
709 if (isempty(desktop))
712 if (!string_is_safe(desktop))
713 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
719 seat = hashmap_get(m->seats, cseat);
721 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
724 if (tty_is_vc(tty)) {
729 else if (seat != m->seat0)
730 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
732 v = vtnr_from_tty(tty);
734 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
738 else if (vtnr != (uint32_t) v)
739 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
741 } else if (tty_is_console(tty)) {
745 else if (seat != m->seat0)
746 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
749 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
753 if (seat_has_vts(seat)) {
754 if (vtnr <= 0 || vtnr > 63)
755 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
758 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
762 r = sd_bus_message_enter_container(message, 'a', "(sv)");
766 if (t == _SESSION_TYPE_INVALID) {
767 if (!isempty(display))
769 else if (!isempty(tty))
772 t = SESSION_UNSPECIFIED;
775 if (c == _SESSION_CLASS_INVALID) {
776 if (t == SESSION_UNSPECIFIED)
777 c = SESSION_BACKGROUND;
783 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
785 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
789 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
794 /* Check if we are already in a logind session. Or if we are in user@.service which is a special PAM session
795 * that avoids creating a logind session. */
796 r = manager_get_user_by_pid(m, leader, NULL);
800 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session or user slice");
803 * Old gdm and lightdm start the user-session on the same VT as
804 * the greeter session. But they destroy the greeter session
805 * after the user-session and want the user-session to take
806 * over the VT. We need to support this for
807 * backwards-compatibility, so make sure we allow new sessions
808 * on a VT that a greeter is running on. Furthermore, to allow
809 * re-logins, we have to allow a greeter to take over a used VT for
810 * the exact same reasons.
812 if (c != SESSION_GREETER &&
814 vtnr < m->seat0->position_count &&
815 m->seat0->positions[vtnr] &&
816 m->seat0->positions[vtnr]->class != SESSION_GREETER)
817 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
819 if (hashmap_size(m->sessions) >= m->sessions_max)
820 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
822 (void) audit_session_from_pid(leader, &audit_id);
823 if (audit_session_is_valid(audit_id)) {
824 /* Keep our session IDs and the audit session IDs in sync */
826 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
829 /* Wut? There's already a session by this name and we
830 * didn't find it above? Weird, then let's not trust
831 * the audit data and let's better register a new
833 if (hashmap_get(m->sessions, id)) {
834 log_warning("Existing logind session ID %s used by new audit session, ignoring.", id);
835 audit_id = AUDIT_SESSION_INVALID;
844 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
847 } while (hashmap_get(m->sessions, id));
850 r = manager_add_user_by_uid(m, uid, &user);
854 r = manager_add_session(m, id, &session);
858 session_set_user(session, user);
860 session->leader = leader;
861 session->audit_id = audit_id;
864 session->remote = remote;
865 session->vtnr = vtnr;
868 session->tty = strdup(tty);
875 if (!isempty(display)) {
876 session->display = strdup(display);
877 if (!session->display) {
883 if (!isempty(remote_user)) {
884 session->remote_user = strdup(remote_user);
885 if (!session->remote_user) {
891 if (!isempty(remote_host)) {
892 session->remote_host = strdup(remote_host);
893 if (!session->remote_host) {
899 if (!isempty(service)) {
900 session->service = strdup(service);
901 if (!session->service) {
907 if (!isempty(desktop)) {
908 session->desktop = strdup(desktop);
909 if (!session->desktop) {
916 r = seat_attach_session(seat, session);
921 r = session_start(session);
925 session->create_message = sd_bus_message_ref(message);
927 #if 0 /// UNNEEDED by elogind
928 /* Now, let's wait until the slice unit and stuff got created. We send the reply back from
929 * session_send_create_reply(). */
931 /* We reply directly. */
933 r = session_send_create_reply(session, NULL);
942 session_add_to_gc_queue(session);
945 user_add_to_gc_queue(user);
950 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
951 Manager *m = userdata;
959 r = sd_bus_message_read(message, "s", &name);
963 r = manager_get_session_from_creds(m, message, name, error, &session);
967 r = session_release(session);
971 #if 1 /// elogind must queue this session
972 session_add_to_gc_queue(session);
974 return sd_bus_reply_method_return(message, NULL);
977 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
978 Manager *m = userdata;
986 r = sd_bus_message_read(message, "s", &name);
990 r = manager_get_session_from_creds(m, message, name, error, &session);
994 return bus_session_method_activate(message, session, error);
997 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
998 const char *session_name, *seat_name;
999 Manager *m = userdata;
1007 /* Same as ActivateSession() but refuses to work if
1008 * the seat doesn't match */
1010 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
1014 r = manager_get_session_from_creds(m, message, session_name, error, &session);
1018 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
1022 if (session->seat != seat)
1023 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
1025 r = session_activate(session);
1029 return sd_bus_reply_method_return(message, NULL);
1032 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1033 Manager *m = userdata;
1041 r = sd_bus_message_read(message, "s", &name);
1045 r = manager_get_session_from_creds(m, message, name, error, &session);
1049 return bus_session_method_lock(message, session, error);
1052 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1053 Manager *m = userdata;
1059 r = bus_verify_polkit_async(
1062 "org.freedesktop.login1.lock-sessions",
1066 &m->polkit_registry,
1071 return 1; /* Will call us back */
1073 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1077 return sd_bus_reply_method_return(message, NULL);
1080 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1082 Manager *m = userdata;
1089 r = sd_bus_message_read(message, "s", &name);
1093 r = manager_get_session_from_creds(m, message, name, error, &session);
1097 return bus_session_method_kill(message, session, error);
1100 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1101 Manager *m = userdata;
1109 r = sd_bus_message_read(message, "u", &uid);
1113 r = manager_get_user_from_creds(m, message, uid, error, &user);
1117 return bus_user_method_kill(message, user, error);
1120 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1121 Manager *m = userdata;
1129 r = sd_bus_message_read(message, "s", &name);
1133 r = manager_get_session_from_creds(m, message, name, error, &session);
1137 return bus_session_method_terminate(message, session, error);
1140 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1141 Manager *m = userdata;
1149 r = sd_bus_message_read(message, "u", &uid);
1153 r = manager_get_user_from_creds(m, message, uid, error, &user);
1157 return bus_user_method_terminate(message, user, error);
1160 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1161 Manager *m = userdata;
1169 r = sd_bus_message_read(message, "s", &name);
1173 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1177 return bus_seat_method_terminate(message, seat, error);
1180 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1181 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1182 _cleanup_free_ char *cc = NULL;
1183 Manager *m = userdata;
1184 int r, b, interactive;
1187 uint32_t uid, auth_uid;
1192 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1196 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
1197 SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1201 if (!uid_is_valid(uid)) {
1202 /* Note that we get the owner UID of the session or user unit,
1203 * not the actual client UID here! */
1204 r = sd_bus_creds_get_owner_uid(creds, &uid);
1209 /* owner_uid is racy, so for authorization we must use euid */
1210 r = sd_bus_creds_get_euid(creds, &auth_uid);
1217 return errno > 0 ? -errno : -ENOENT;
1219 r = bus_verify_polkit_async(
1222 uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
1223 "org.freedesktop.login1.set-user-linger",
1227 &m->polkit_registry,
1232 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1234 mkdir_p_label("/var/lib/elogind", 0755);
1236 r = mkdir_safe_label("/var/lib/elogind/linger", 0755, 0, 0, false);
1240 cc = cescape(pw->pw_name);
1244 path = strjoina("/var/lib/elogind/linger/", cc);
1252 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1259 if (r < 0 && errno != ENOENT)
1262 u = hashmap_get(m->users, UID_TO_PTR(uid));
1264 user_add_to_gc_queue(u);
1267 return sd_bus_reply_method_return(message, NULL);
1270 static int trigger_device(Manager *m, struct udev_device *d) {
1271 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1272 struct udev_list_entry *first, *item;
1277 e = udev_enumerate_new(m->udev);
1282 r = udev_enumerate_add_match_parent(e, d);
1287 r = udev_enumerate_scan_devices(e);
1291 first = udev_enumerate_get_list_entry(e);
1292 udev_list_entry_foreach(item, first) {
1293 _cleanup_free_ char *t = NULL;
1296 p = udev_list_entry_get_name(item);
1298 t = strappend(p, "/uevent");
1302 (void) write_string_file(t, "change", 0);
1308 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1309 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1310 _cleanup_free_ char *rule = NULL, *file = NULL;
1311 const char *id_for_seat;
1318 d = udev_device_new_from_syspath(m->udev, sysfs);
1322 if (!udev_device_has_tag(d, "seat"))
1325 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1329 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1332 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1335 mkdir_p_label("/etc/udev/rules.d", 0755);
1336 r = write_string_file_atomic_label(file, rule);
1340 return trigger_device(m, d);
1343 static int flush_devices(Manager *m) {
1344 _cleanup_closedir_ DIR *d;
1348 d = opendir("/etc/udev/rules.d");
1350 if (errno != ENOENT)
1351 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1355 FOREACH_DIRENT_ALL(de, d, break) {
1356 if (!dirent_is_file(de))
1359 if (!startswith(de->d_name, "72-seat-"))
1362 if (!endswith(de->d_name, ".rules"))
1365 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1366 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1370 return trigger_device(m, NULL);
1373 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1374 const char *sysfs, *seat;
1375 Manager *m = userdata;
1381 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1385 if (!path_startswith(sysfs, "/sys"))
1386 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1388 if (!seat_name_is_valid(seat))
1389 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1391 r = bus_verify_polkit_async(
1394 "org.freedesktop.login1.attach-device",
1398 &m->polkit_registry,
1403 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1405 r = attach_device(m, seat, sysfs);
1409 return sd_bus_reply_method_return(message, NULL);
1412 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1413 Manager *m = userdata;
1419 r = sd_bus_message_read(message, "b", &interactive);
1423 r = bus_verify_polkit_async(
1426 "org.freedesktop.login1.flush-devices",
1430 &m->polkit_registry,
1435 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1437 r = flush_devices(m);
1441 return sd_bus_reply_method_return(message, NULL);
1444 static int have_multiple_sessions(
1453 /* Check for other users' sessions. Greeter sessions do not
1454 * count, and non-login sessions do not count either. */
1455 HASHMAP_FOREACH(session, m->sessions, i)
1456 if (session->class == SESSION_USER &&
1457 session->user->uid != uid)
1463 #if 0 /// elogind has its own variant in elogind-dbus.c
1464 static int bus_manager_log_shutdown(
1466 const char *unit_name) {
1473 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1474 p = "MESSAGE=System is powering down";
1475 q = "SHUTDOWN=power-off";
1476 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1477 p = "MESSAGE=System is rebooting";
1478 q = "SHUTDOWN=reboot";
1479 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1480 p = "MESSAGE=System is halting";
1481 q = "SHUTDOWN=halt";
1482 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1483 p = "MESSAGE=System is rebooting with kexec";
1484 q = "SHUTDOWN=kexec";
1486 p = "MESSAGE=System is shutting down";
1490 if (isempty(m->wall_message))
1491 p = strjoina(p, ".");
1493 p = strjoina(p, " (", m->wall_message, ").");
1495 return log_struct(LOG_NOTICE,
1496 "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
1503 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1504 Manager *m = userdata;
1509 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1513 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1518 if (until <= now(CLOCK_MONOTONIC))
1521 /* We want to ignore the lid switch for a while after each
1522 * suspend, and after boot-up. Hence let's install a timer for
1523 * this. As long as the event source exists we ignore the lid
1526 if (m->lid_switch_ignore_event_source) {
1529 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1536 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1538 r = sd_event_add_time(
1540 &m->lid_switch_ignore_event_source,
1543 lid_switch_ignore_handler, m);
1548 #if 0 /// elogind-dbus.c needs to access this
1549 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1551 int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1554 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1555 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1556 [INHIBIT_SLEEP] = "PrepareForSleep"
1559 int active = _active;
1563 assert(w < _INHIBIT_WHAT_MAX);
1564 assert(signal_name[w]);
1566 return sd_bus_emit_signal(m->bus,
1567 "/org/freedesktop/login1",
1568 "org.freedesktop.login1.Manager",
1574 #if 0 /// elogind has its own variant in elogind-dbus.c
1575 static int execute_shutdown_or_sleep(
1578 const char *unit_name,
1579 sd_bus_error *error) {
1581 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1588 assert(w < _INHIBIT_WHAT_MAX);
1591 if (w == INHIBIT_SHUTDOWN)
1592 bus_manager_log_shutdown(m, unit_name);
1594 r = sd_bus_call_method(
1596 "org.freedesktop.systemd1",
1597 "/org/freedesktop/systemd1",
1598 "org.freedesktop.systemd1.Manager",
1602 "ss", unit_name, "replace-irreversibly");
1606 r = sd_bus_message_read(reply, "o", &p);
1616 m->action_unit = unit_name;
1617 free(m->action_job);
1621 /* Make sure the lid switch is ignored for a while */
1622 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1627 /* Tell people that they now may take a lock again */
1628 (void) send_prepare_for(m, w, false);
1634 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1636 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1637 Inhibitor *offending = NULL;
1642 #if 0 /// elogind has no action_job, but a pending_action
1643 if (manager->action_what == 0 || manager->action_job)
1645 if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
1649 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1650 _cleanup_free_ char *comm = NULL, *u = NULL;
1655 (void) get_process_comm(offending->pid, &comm);
1656 u = uid_to_name(offending->uid);
1658 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1659 offending->uid, strna(u),
1660 offending->pid, strna(comm));
1663 /* Actually do the operation */
1664 #if 0 /// elogind has no action_unit but a pending_action
1665 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1667 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
1670 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1671 bus_error_message(&error, r));
1674 #if 0 /// elogind has no action_unit but a pending_action
1675 manager->action_unit = NULL;
1676 manager->action_what = 0;
1679 manager->pending_action = HANDLE_IGNORE;
1680 manager->action_what = 0;
1681 /* It is not a critical error for elogind if suspending fails */
1688 static int manager_inhibit_timeout_handler(
1693 Manager *manager = userdata;
1697 assert(manager->inhibit_timeout_source == s);
1699 r = manager_dispatch_delayed(manager, true);
1700 return (r < 0) ? r : 0;
1703 #if 0 /// elogind does not have unit_name but action
1704 static int delay_shutdown_or_sleep(
1707 const char *unit_name) {
1710 int delay_shutdown_or_sleep(
1713 HandleAction action) {
1720 assert(w < _INHIBIT_WHAT_MAX);
1721 #if 0 /// UNNEEDED by elogind
1725 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1727 if (m->inhibit_timeout_source) {
1728 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1730 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1732 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1734 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1736 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1737 timeout_val, 0, manager_inhibit_timeout_handler, m);
1742 #if 0 /// elogind does not have unit_name but pendig_action
1743 m->action_unit = unit_name;
1745 m->pending_action = action;
1752 int bus_manager_shutdown_or_sleep_now_or_later(
1754 #if 0 /// elogind has HandleAction instead of const char* unit_name
1755 const char *unit_name,
1758 HandleAction unit_name,
1761 sd_bus_error *error) {
1766 #if 0 /// for elogind only w has to be checked.
1769 assert(w <= _INHIBIT_WHAT_MAX);
1770 assert(!m->action_job);
1773 assert(w <= _INHIBIT_WHAT_MAX);
1776 /* Tell everybody to prepare for shutdown/sleep */
1777 (void) send_prepare_for(m, w, true);
1780 m->inhibit_delay_max > 0 &&
1781 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1783 log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
1784 handle_action_to_string(unit_name),
1785 delayed ? "" : "NOT ");
1787 /* Shutdown is delayed, keep in mind what we
1788 * want to do, and start a timeout */
1789 r = delay_shutdown_or_sleep(m, w, unit_name);
1791 /* Shutdown is not delayed, execute it
1793 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1798 static int verify_shutdown_creds(
1800 sd_bus_message *message,
1804 const char *action_multiple_sessions,
1805 const char *action_ignore_inhibit,
1806 sd_bus_error *error) {
1808 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1809 bool multiple_sessions, blocked;
1816 assert(w <= _INHIBIT_WHAT_MAX);
1818 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1822 r = sd_bus_creds_get_euid(creds, &uid);
1826 r = have_multiple_sessions(m, uid);
1830 multiple_sessions = r > 0;
1831 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1833 if (multiple_sessions && action_multiple_sessions) {
1834 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1838 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1841 if (blocked && action_ignore_inhibit) {
1842 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1846 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1849 if (!multiple_sessions && !blocked && action) {
1850 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1854 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1860 static int method_do_shutdown_or_sleep(
1862 sd_bus_message *message,
1863 #if 0 /// elogind has HandleAction instead of const char* unit_name
1864 const char *unit_name,
1866 HandleAction unit_name,
1870 const char *action_multiple_sessions,
1871 const char *action_ignore_inhibit,
1872 const char *sleep_verb,
1873 sd_bus_error *error) {
1879 #if 0 /// elogind does not need this to be checked
1883 assert(w <= _INHIBIT_WHAT_MAX);
1885 r = sd_bus_message_read(message, "b", &interactive);
1889 log_debug_elogind("%s called with action '%s', sleep '%s' (%sinteractive)",
1890 __FUNCTION__, action, sleep_verb,
1891 interactive ? "" : "NOT ");
1892 /* Don't allow multiple jobs being executed at the same time */
1894 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1897 #if 0 /// Within elogind the manager m must be provided, too
1898 r = can_sleep(sleep_verb);
1900 r = can_sleep(m, sleep_verb);
1906 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1909 #if 0 /// Within elogind it does not make sense to verify shutdown creds when suspending
1910 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1911 action_ignore_inhibit, error);
1915 if (IN_SET(unit_name, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) {
1916 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1917 action_ignore_inhibit, error);
1918 log_debug_elogind("verify_shutdown_creds() returned %d", r);
1924 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1928 return sd_bus_reply_method_return(message, NULL);
1931 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1932 Manager *m = userdata;
1934 log_debug_elogind("%s called", __FUNCTION__);
1935 return method_do_shutdown_or_sleep(
1937 #if 0 /// elogind uses HandleAction instead of const char* unti names
1938 SPECIAL_POWEROFF_TARGET,
1943 "org.freedesktop.login1.power-off",
1944 "org.freedesktop.login1.power-off-multiple-sessions",
1945 "org.freedesktop.login1.power-off-ignore-inhibit",
1950 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1951 Manager *m = userdata;
1953 log_debug_elogind("%s called", __FUNCTION__);
1954 return method_do_shutdown_or_sleep(
1956 #if 0 /// elogind uses HandleAction instead of const char* unti names
1957 SPECIAL_REBOOT_TARGET,
1962 "org.freedesktop.login1.reboot",
1963 "org.freedesktop.login1.reboot-multiple-sessions",
1964 "org.freedesktop.login1.reboot-ignore-inhibit",
1969 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1970 Manager *m = userdata;
1972 log_debug_elogind("%s called", __FUNCTION__);
1973 return method_do_shutdown_or_sleep(
1975 #if 0 /// elogind uses HandleAction instead of const char* unti names
1976 SPECIAL_HALT_TARGET,
1981 "org.freedesktop.login1.halt",
1982 "org.freedesktop.login1.halt-multiple-sessions",
1983 "org.freedesktop.login1.halt-ignore-inhibit",
1988 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1989 Manager *m = userdata;
1991 log_debug_elogind("%s called", __FUNCTION__);
1992 return method_do_shutdown_or_sleep(
1994 #if 0 /// elogind uses HandleAction instead of const char* unti names
1995 SPECIAL_SUSPEND_TARGET,
2000 "org.freedesktop.login1.suspend",
2001 "org.freedesktop.login1.suspend-multiple-sessions",
2002 "org.freedesktop.login1.suspend-ignore-inhibit",
2007 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2008 Manager *m = userdata;
2010 log_debug_elogind("%s called", __FUNCTION__);
2011 return method_do_shutdown_or_sleep(
2013 #if 0 /// elogind uses HandleAction instead of const char* unti names
2014 SPECIAL_HIBERNATE_TARGET,
2019 "org.freedesktop.login1.hibernate",
2020 "org.freedesktop.login1.hibernate-multiple-sessions",
2021 "org.freedesktop.login1.hibernate-ignore-inhibit",
2026 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2027 Manager *m = userdata;
2029 log_debug_elogind("%s called", __FUNCTION__);
2030 return method_do_shutdown_or_sleep(
2032 #if 0 /// elogind uses HandleAction instead of const char* unti names
2033 SPECIAL_HYBRID_SLEEP_TARGET,
2035 "org.freedesktop.login1.hibernate",
2036 "org.freedesktop.login1.hibernate-multiple-sessions",
2037 "org.freedesktop.login1.hibernate-ignore-inhibit",
2042 static int method_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2043 Manager *m = userdata;
2045 return method_do_shutdown_or_sleep(
2047 SPECIAL_SUSPEND_TO_HIBERNATE_TARGET,
2049 HANDLE_HYBRID_SLEEP,
2052 "org.freedesktop.login1.hibernate",
2053 "org.freedesktop.login1.hibernate-multiple-sessions",
2054 "org.freedesktop.login1.hibernate-ignore-inhibit",
2059 static int nologin_timeout_handler(
2064 Manager *m = userdata;
2066 log_info("Creating /run/nologin, blocking further logins...");
2069 create_shutdown_run_nologin_or_warn() >= 0;
2074 static int update_schedule_file(Manager *m) {
2075 _cleanup_free_ char *temp_path = NULL;
2076 _cleanup_fclose_ FILE *f = NULL;
2081 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, false);
2083 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
2085 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
2087 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
2089 (void) fchmod(fileno(f), 0644);
2095 m->scheduled_shutdown_timeout,
2096 m->enable_wall_messages,
2097 m->scheduled_shutdown_type);
2099 if (!isempty(m->wall_message)) {
2100 _cleanup_free_ char *t;
2102 t = cescape(m->wall_message);
2108 fprintf(f, "WALL_MESSAGE=%s\n", t);
2111 r = fflush_and_check(f);
2115 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
2123 (void) unlink(temp_path);
2124 (void) unlink("/run/systemd/shutdown/scheduled");
2126 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
2129 #if 0 /// elogind must access this from elogind-dbus.c
2130 static void reset_scheduled_shutdown(Manager *m) {
2132 void reset_scheduled_shutdown(Manager *m) {
2136 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2137 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2138 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2140 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2141 m->scheduled_shutdown_timeout = 0;
2142 m->shutdown_dry_run = false;
2144 if (m->unlink_nologin) {
2145 (void) unlink_or_warn("/run/nologin");
2146 m->unlink_nologin = false;
2149 (void) unlink("/run/systemd/shutdown/scheduled");
2152 #if 0 /// elogind has its own variant in elogind-dbus.c
2153 static int manager_scheduled_shutdown_handler(
2158 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2159 Manager *m = userdata;
2165 if (isempty(m->scheduled_shutdown_type))
2168 if (streq(m->scheduled_shutdown_type, "poweroff"))
2169 target = SPECIAL_POWEROFF_TARGET;
2170 else if (streq(m->scheduled_shutdown_type, "reboot"))
2171 target = SPECIAL_REBOOT_TARGET;
2172 else if (streq(m->scheduled_shutdown_type, "halt"))
2173 target = SPECIAL_HALT_TARGET;
2175 assert_not_reached("unexpected shutdown type");
2177 /* Don't allow multiple jobs being executed at the same time */
2178 if (m->action_what) {
2180 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
2184 if (m->shutdown_dry_run) {
2185 /* We do not process delay inhibitors here. Otherwise, we
2186 * would have to be considered "in progress" (like the check
2187 * above) for some seconds after our admin has seen the final
2190 bus_manager_log_shutdown(m, target);
2191 log_info("Running in dry run, suppressing action.");
2192 reset_scheduled_shutdown(m);
2197 r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
2199 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2206 reset_scheduled_shutdown(m);
2211 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2212 Manager *m = userdata;
2213 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2214 const char *action_multiple_sessions = NULL;
2215 const char *action_ignore_inhibit = NULL;
2216 const char *action = NULL;
2220 bool dry_run = false;
2225 log_debug_elogind("%s called", __FUNCTION__);
2226 r = sd_bus_message_read(message, "st", &type, &elapse);
2230 if (startswith(type, "dry-")) {
2235 if (streq(type, "poweroff")) {
2236 action = "org.freedesktop.login1.power-off";
2237 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2238 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2239 } else if (streq(type, "reboot")) {
2240 action = "org.freedesktop.login1.reboot";
2241 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2242 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2243 } else if (streq(type, "halt")) {
2244 action = "org.freedesktop.login1.halt";
2245 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2246 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
2248 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2250 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2251 action, action_multiple_sessions, action_ignore_inhibit, error);
2255 if (m->scheduled_shutdown_timeout_source) {
2256 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2258 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2260 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2262 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2264 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2265 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2267 return log_error_errno(r, "sd_event_add_time() failed: %m");
2270 r = free_and_strdup(&m->scheduled_shutdown_type, type);
2272 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2276 m->shutdown_dry_run = dry_run;
2278 if (m->nologin_timeout_source) {
2279 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2281 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2283 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2285 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2287 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2288 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2290 return log_error_errno(r, "sd_event_add_time() failed: %m");
2293 m->scheduled_shutdown_timeout = elapse;
2295 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2297 const char *tty = NULL;
2299 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2300 (void) sd_bus_creds_get_tty(creds, &tty);
2302 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2304 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2309 r = manager_setup_wall_message_timer(m);
2313 r = update_schedule_file(m);
2317 return sd_bus_reply_method_return(message, NULL);
2320 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2321 Manager *m = userdata;
2323 #if 1 /// elogind needs to construct the message to allow extra wall messages
2324 _cleanup_free_ char *l = NULL;
2330 log_debug_elogind("%s called", __FUNCTION__);
2331 cancelled = m->scheduled_shutdown_type != NULL;
2332 reset_scheduled_shutdown(m);
2335 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2336 const char *tty = NULL;
2340 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2342 (void) sd_bus_creds_get_uid(creds, &uid);
2343 (void) sd_bus_creds_get_tty(creds, &tty);
2346 #if 0 /// elogind wants to allow extra cancellation messages
2347 utmp_wall("The system shutdown has been cancelled",
2348 uid_to_name(uid), tty, logind_wall_tty_filter, m);
2350 r = asprintf(&l, "%s%sThe system shutdown has been cancelled!",
2351 strempty(m->wall_message),
2352 isempty(m->wall_message) ? "" : "\n");
2358 utmp_wall(l, uid_to_name(uid), tty, logind_wall_tty_filter, m);
2362 return sd_bus_reply_method_return(message, "b", cancelled);
2365 static int method_can_shutdown_or_sleep(
2367 sd_bus_message *message,
2370 const char *action_multiple_sessions,
2371 const char *action_ignore_inhibit,
2372 const char *sleep_verb,
2373 sd_bus_error *error) {
2375 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2376 bool multiple_sessions, challenge, blocked;
2377 const char *result = NULL;
2384 assert(w <= _INHIBIT_WHAT_MAX);
2386 assert(action_multiple_sessions);
2387 assert(action_ignore_inhibit);
2390 #if 0 /// elogind needs to have the manager being passed
2391 r = can_sleep(sleep_verb);
2393 r = can_sleep(m, sleep_verb);
2398 return sd_bus_reply_method_return(message, "s", "na");
2401 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2405 r = sd_bus_creds_get_euid(creds, &uid);
2409 r = have_multiple_sessions(m, uid);
2413 multiple_sessions = r > 0;
2414 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2416 if (multiple_sessions) {
2417 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2424 result = "challenge";
2430 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2434 if (r > 0 && !result)
2436 else if (challenge && (!result || streq(result, "yes")))
2437 result = "challenge";
2442 if (!multiple_sessions && !blocked) {
2443 /* If neither inhibit nor multiple sessions
2444 * apply then just check the normal policy */
2446 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2453 result = "challenge";
2458 return sd_bus_reply_method_return(message, "s", result);
2461 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2462 Manager *m = userdata;
2464 return method_can_shutdown_or_sleep(
2467 "org.freedesktop.login1.power-off",
2468 "org.freedesktop.login1.power-off-multiple-sessions",
2469 "org.freedesktop.login1.power-off-ignore-inhibit",
2474 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2475 Manager *m = userdata;
2477 return method_can_shutdown_or_sleep(
2480 "org.freedesktop.login1.reboot",
2481 "org.freedesktop.login1.reboot-multiple-sessions",
2482 "org.freedesktop.login1.reboot-ignore-inhibit",
2487 static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2488 Manager *m = userdata;
2490 return method_can_shutdown_or_sleep(
2493 "org.freedesktop.login1.halt",
2494 "org.freedesktop.login1.halt-multiple-sessions",
2495 "org.freedesktop.login1.halt-ignore-inhibit",
2500 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2501 Manager *m = userdata;
2503 return method_can_shutdown_or_sleep(
2506 "org.freedesktop.login1.suspend",
2507 "org.freedesktop.login1.suspend-multiple-sessions",
2508 "org.freedesktop.login1.suspend-ignore-inhibit",
2513 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2514 Manager *m = userdata;
2516 return method_can_shutdown_or_sleep(
2519 "org.freedesktop.login1.hibernate",
2520 "org.freedesktop.login1.hibernate-multiple-sessions",
2521 "org.freedesktop.login1.hibernate-ignore-inhibit",
2526 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2527 Manager *m = userdata;
2529 return method_can_shutdown_or_sleep(
2532 "org.freedesktop.login1.hibernate",
2533 "org.freedesktop.login1.hibernate-multiple-sessions",
2534 "org.freedesktop.login1.hibernate-ignore-inhibit",
2539 static int method_can_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2540 Manager *m = userdata;
2542 return method_can_shutdown_or_sleep(
2545 "org.freedesktop.login1.hibernate",
2546 "org.freedesktop.login1.hibernate-multiple-sessions",
2547 "org.freedesktop.login1.hibernate-ignore-inhibit",
2548 "suspend-to-hibernate",
2552 static int property_get_reboot_to_firmware_setup(
2555 const char *interface,
2556 const char *property,
2557 sd_bus_message *reply,
2559 sd_bus_error *error) {
2560 #if 0 /// elogind does not support EFI
2567 r = efi_get_reboot_to_firmware();
2568 if (r < 0 && r != -EOPNOTSUPP)
2569 log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
2571 return sd_bus_message_append(reply, "b", r > 0);
2573 return sd_bus_message_append(reply, "b", false);
2577 static int method_set_reboot_to_firmware_setup(
2578 sd_bus_message *message,
2580 sd_bus_error *error) {
2583 Manager *m = userdata;
2588 r = sd_bus_message_read(message, "b", &b);
2592 r = bus_verify_polkit_async(message,
2594 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2598 &m->polkit_registry,
2603 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2605 #if 0 /// elogind does not support EFI
2606 r = efi_set_reboot_to_firmware(b);
2611 return sd_bus_reply_method_return(message, NULL);
2614 static int method_can_reboot_to_firmware_setup(
2615 sd_bus_message *message,
2617 sd_bus_error *error) {
2619 #if 0 /// elogind does not support EFI
2623 Manager *m = userdata;
2628 r = efi_reboot_to_firmware_supported();
2630 if (r != -EOPNOTSUPP)
2631 log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m");
2633 return sd_bus_reply_method_return(message, "s", "na");
2636 r = bus_test_polkit(message,
2638 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2649 result = "challenge";
2653 return sd_bus_reply_method_return(message, "s", result);
2655 return sd_bus_reply_method_return(message, "s", "no");
2659 static int method_set_wall_message(
2660 sd_bus_message *message,
2662 sd_bus_error *error) {
2665 Manager *m = userdata;
2667 int enable_wall_messages;
2672 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2676 #if 0 /// elogind only calls this for shutdown/reboot, which already needs authorization.
2677 r = bus_verify_polkit_async(message,
2679 "org.freedesktop.login1.set-wall-message",
2683 &m->polkit_registry,
2688 return 1; /* Will call us back */
2691 r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
2695 m->enable_wall_messages = enable_wall_messages;
2697 return sd_bus_reply_method_return(message, NULL);
2700 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2701 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2702 const char *who, *why, *what, *mode;
2703 _cleanup_free_ char *id = NULL;
2704 _cleanup_close_ int fifo_fd = -1;
2705 Manager *m = userdata;
2706 Inhibitor *i = NULL;
2716 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2720 w = inhibit_what_from_string(what);
2722 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2724 mm = inhibit_mode_from_string(mode);
2726 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2728 /* Delay is only supported for shutdown/sleep */
2729 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2730 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2732 /* Don't allow taking delay locks while we are already
2733 * executing the operation. We shouldn't create the impression
2734 * that the lock was successful if the machine is about to go
2735 * down/suspend any moment. */
2736 if (m->action_what & w)
2737 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2739 r = bus_verify_polkit_async(
2742 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2743 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2744 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2745 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2746 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2747 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2748 "org.freedesktop.login1.inhibit-handle-lid-switch",
2752 &m->polkit_registry,
2757 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2759 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2763 r = sd_bus_creds_get_euid(creds, &uid);
2767 r = sd_bus_creds_get_pid(creds, &pid);
2771 if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
2772 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
2777 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2780 } while (hashmap_get(m->inhibitors, id));
2782 r = manager_add_inhibitor(m, id, &i);
2790 i->why = strdup(why);
2791 i->who = strdup(who);
2793 if (!i->why || !i->who) {
2798 fifo_fd = inhibitor_create_fifo(i);
2806 return sd_bus_reply_method_return(message, "h", fifo_fd);
2815 const sd_bus_vtable manager_vtable[] = {
2816 SD_BUS_VTABLE_START(0),
2818 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2819 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2821 #if 0 /// UNNEEDED by elogind
2822 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2824 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2825 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2826 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2827 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2828 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2829 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2830 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2831 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2832 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2833 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2834 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2835 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2836 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2837 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2838 SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
2839 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2840 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2841 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2842 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2843 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2844 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2845 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2846 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2847 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
2848 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
2849 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
2850 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
2851 SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
2852 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
2853 SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2855 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2856 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2857 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2858 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2859 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2860 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2861 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2862 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2863 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2864 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2865 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2866 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2867 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2868 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2869 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2870 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2871 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2872 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2873 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2874 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2875 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2876 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2877 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2878 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2879 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2880 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2881 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2882 SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2883 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2884 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2885 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2886 SD_BUS_METHOD("SuspendToHibernate", "b", NULL, method_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2887 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2888 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2889 SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2890 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2891 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2892 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2893 SD_BUS_METHOD("CanSuspendToHibernate", NULL, "s", method_can_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2894 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2895 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2896 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2897 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2898 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2899 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2901 SD_BUS_SIGNAL("SessionNew", "so", 0),
2902 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2903 SD_BUS_SIGNAL("UserNew", "uo", 0),
2904 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2905 SD_BUS_SIGNAL("SeatNew", "so", 0),
2906 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2907 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2908 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2913 #if 0 /// UNNEEDED by elogind
2914 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2923 if (streq(result, "done"))
2924 r = session_send_create_reply(s, NULL);
2926 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
2928 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2929 r = session_send_create_reply(s, &e);
2935 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2936 const char *path, *result, *unit;
2937 Manager *m = userdata;
2946 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2948 bus_log_parse_error(r);
2952 if (m->action_job && streq(m->action_job, path)) {
2953 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2955 /* Tell people that they now may take a lock again */
2956 (void) send_prepare_for(m, m->action_what, false);
2958 m->action_job = mfree(m->action_job);
2959 m->action_unit = NULL;
2964 session = hashmap_get(m->session_units, unit);
2965 if (session && streq_ptr(path, session->scope_job)) {
2966 session->scope_job = mfree(session->scope_job);
2967 session_jobs_reply(session, unit, result);
2969 session_save(session);
2970 user_save(session->user);
2971 session_add_to_gc_queue(session);
2974 user = hashmap_get(m->user_units, unit);
2976 (streq_ptr(path, user->service_job) ||
2977 streq_ptr(path, user->slice_job))) {
2979 if (streq_ptr(path, user->service_job))
2980 user->service_job = mfree(user->service_job);
2982 if (streq_ptr(path, user->slice_job))
2983 user->slice_job = mfree(user->slice_job);
2985 LIST_FOREACH(sessions_by_user, session, user->sessions)
2986 session_jobs_reply(session, unit, result);
2989 user_add_to_gc_queue(user);
2995 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2996 const char *path, *unit;
2997 Manager *m = userdata;
3005 r = sd_bus_message_read(message, "so", &unit, &path);
3007 bus_log_parse_error(r);
3011 session = hashmap_get(m->session_units, unit);
3013 session_add_to_gc_queue(session);
3015 user = hashmap_get(m->user_units, unit);
3017 user_add_to_gc_queue(user);
3022 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3023 _cleanup_free_ char *unit = NULL;
3024 Manager *m = userdata;
3033 path = sd_bus_message_get_path(message);
3037 r = unit_name_from_dbus_path(path, &unit);
3038 if (r == -EINVAL) /* not a unit */
3045 session = hashmap_get(m->session_units, unit);
3047 session_add_to_gc_queue(session);
3049 user = hashmap_get(m->user_units, unit);
3051 user_add_to_gc_queue(user);
3056 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3057 Manager *m = userdata;
3065 r = sd_bus_message_read(message, "b", &b);
3067 bus_log_parse_error(r);
3074 /* systemd finished reloading, let's recheck all our sessions */
3075 log_debug("System manager has been reloaded, rechecking sessions...");
3077 HASHMAP_FOREACH(session, m->sessions, i)
3078 session_add_to_gc_queue(session);
3084 int manager_send_changed(Manager *manager, const char *property, ...) {
3089 l = strv_from_stdarg_alloca(property);
3091 return sd_bus_emit_properties_changed_strv(
3093 "/org/freedesktop/login1",
3094 "org.freedesktop.login1.Manager",
3098 #if 0 /// UNNEEDED by elogind
3099 static int strdup_job(sd_bus_message *reply, char **job) {
3104 r = sd_bus_message_read(reply, "o", &j);
3116 int manager_start_slice(
3119 const char *description,
3123 sd_bus_error *error,
3126 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3133 r = sd_bus_message_new_method_call(
3136 "org.freedesktop.systemd1",
3137 "/org/freedesktop/systemd1",
3138 "org.freedesktop.systemd1.Manager",
3139 "StartTransientUnit");
3143 r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
3147 r = sd_bus_message_open_container(m, 'a', "(sv)");
3151 if (!isempty(description)) {
3152 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3157 if (!isempty(after)) {
3158 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3163 if (!isempty(after2)) {
3164 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3169 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3173 r = sd_bus_message_close_container(m);
3177 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3181 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3185 return strdup_job(reply, job);
3188 int manager_start_scope(
3193 const char *description,
3197 sd_bus_error *error,
3200 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3208 r = sd_bus_message_new_method_call(
3211 "org.freedesktop.systemd1",
3212 "/org/freedesktop/systemd1",
3213 "org.freedesktop.systemd1.Manager",
3214 "StartTransientUnit");
3218 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3222 r = sd_bus_message_open_container(m, 'a', "(sv)");
3226 if (!isempty(slice)) {
3227 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3232 if (!isempty(description)) {
3233 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3238 if (!isempty(after)) {
3239 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3244 if (!isempty(after2)) {
3245 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3250 /* cgroup empty notification is not available in containers
3251 * currently. To make this less problematic, let's shorten the
3252 * stop timeout for sessions, so that we don't wait
3255 /* Make sure that the session shells are terminated with
3256 * SIGHUP since bash and friends tend to ignore SIGTERM */
3257 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3261 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3265 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3269 r = sd_bus_message_close_container(m);
3273 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3277 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3281 return strdup_job(reply, job);
3284 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3285 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3292 r = sd_bus_call_method(
3294 "org.freedesktop.systemd1",
3295 "/org/freedesktop/systemd1",
3296 "org.freedesktop.systemd1.Manager",
3300 "ss", unit, "replace");
3304 return strdup_job(reply, job);
3307 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3308 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3315 r = sd_bus_call_method(
3317 "org.freedesktop.systemd1",
3318 "/org/freedesktop/systemd1",
3319 "org.freedesktop.systemd1.Manager",
3323 "ss", unit, "fail");
3325 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3326 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3329 sd_bus_error_free(error);
3336 return strdup_job(reply, job);
3339 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3340 _cleanup_free_ char *path = NULL;
3346 path = unit_dbus_path_from_name(scope);
3350 r = sd_bus_call_method(
3352 "org.freedesktop.systemd1",
3354 "org.freedesktop.systemd1.Scope",
3360 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3361 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3362 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3363 sd_bus_error_free(error);
3373 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3377 return sd_bus_call_method(
3379 "org.freedesktop.systemd1",
3380 "/org/freedesktop/systemd1",
3381 "org.freedesktop.systemd1.Manager",
3385 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3388 int manager_unit_is_active(Manager *manager, const char *unit) {
3389 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3390 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3391 _cleanup_free_ char *path = NULL;
3398 path = unit_dbus_path_from_name(unit);
3402 r = sd_bus_get_property(
3404 "org.freedesktop.systemd1",
3406 "org.freedesktop.systemd1.Unit",
3412 /* systemd might have droppped off momentarily, let's
3413 * not make this an error */
3414 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3415 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3418 /* If the unit is already unloaded then it's not
3420 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3421 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3427 r = sd_bus_message_read(reply, "s", &state);
3431 return !streq(state, "inactive") && !streq(state, "failed");
3434 int manager_job_is_active(Manager *manager, const char *path) {
3435 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3436 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3442 r = sd_bus_get_property(
3444 "org.freedesktop.systemd1",
3446 "org.freedesktop.systemd1.Job",
3452 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3453 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3456 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3462 /* We don't actually care about the state really. The fact
3463 * that we could read the job state is enough for us */