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"
57 static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
59 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
64 /* Get client login session. This is not what you are looking for these days,
65 * as apps may instead belong to a user service unit. This includes terminal
66 * emulators and hence command-line apps. */
67 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
71 r = sd_bus_creds_get_session(creds, &name);
77 session = hashmap_get(m->sessions, name);
85 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
86 "Caller does not belong to any known session");
89 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
97 return get_sender_session(m, message, error, ret);
99 session = hashmap_get(m->sessions, name);
101 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
107 static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
109 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
114 /* Note that we get the owner UID of the session, not the actual client UID here! */
115 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
119 r = sd_bus_creds_get_owner_uid(creds, &uid);
125 user = hashmap_get(m->users, UID_TO_PTR(uid));
133 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "Caller does not belong to any logged in user or lingering user");
136 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
143 if (!uid_is_valid(uid))
144 return get_sender_user(m, message, error, ret);
146 user = hashmap_get(m->users, UID_TO_PTR(uid));
148 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "User ID "UID_FMT" is not logged in or lingering", uid);
154 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
165 r = manager_get_session_from_creds(m, message, NULL, error, &session);
169 seat = session->seat;
171 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
173 seat = hashmap_get(m->seats, name);
175 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
182 static int property_get_idle_hint(
185 const char *interface,
186 const char *property,
187 sd_bus_message *reply,
189 sd_bus_error *error) {
191 Manager *m = userdata;
197 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
200 static int property_get_idle_since_hint(
203 const char *interface,
204 const char *property,
205 sd_bus_message *reply,
207 sd_bus_error *error) {
209 Manager *m = userdata;
210 dual_timestamp t = DUAL_TIMESTAMP_NULL;
216 manager_get_idle_hint(m, &t);
218 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
221 static int property_get_inhibited(
224 const char *interface,
225 const char *property,
226 sd_bus_message *reply,
228 sd_bus_error *error) {
230 Manager *m = userdata;
237 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
239 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
242 static int property_get_preparing(
245 const char *interface,
246 const char *property,
247 sd_bus_message *reply,
249 sd_bus_error *error) {
251 Manager *m = userdata;
258 if (streq(property, "PreparingForShutdown"))
259 b = !!(m->action_what & INHIBIT_SHUTDOWN);
261 b = !!(m->action_what & INHIBIT_SLEEP);
263 return sd_bus_message_append(reply, "b", b);
266 static int property_get_scheduled_shutdown(
269 const char *interface,
270 const char *property,
271 sd_bus_message *reply,
273 sd_bus_error *error) {
275 Manager *m = userdata;
282 r = sd_bus_message_open_container(reply, 'r', "st");
286 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
290 return sd_bus_message_close_container(reply);
293 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
295 static int property_get_docked(
298 const char *interface,
299 const char *property,
300 sd_bus_message *reply,
302 sd_bus_error *error) {
304 Manager *m = userdata;
310 return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
313 static int property_get_current_sessions(
316 const char *interface,
317 const char *property,
318 sd_bus_message *reply,
320 sd_bus_error *error) {
322 Manager *m = userdata;
328 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
331 static int property_get_current_inhibitors(
334 const char *interface,
335 const char *property,
336 sd_bus_message *reply,
338 sd_bus_error *error) {
340 Manager *m = userdata;
346 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
349 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
350 _cleanup_free_ char *p = NULL;
351 Manager *m = userdata;
359 r = sd_bus_message_read(message, "s", &name);
363 r = manager_get_session_from_creds(m, message, name, error, &session);
367 p = session_bus_path(session);
371 return sd_bus_reply_method_return(message, "o", p);
374 /* Get login session of a process. This is not what you are looking for these days,
375 * as apps may instead belong to a user service unit. This includes terminal
376 * emulators and hence command-line apps. */
377 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
378 _cleanup_free_ char *p = NULL;
379 Session *session = NULL;
380 Manager *m = userdata;
387 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
389 r = sd_bus_message_read(message, "u", &pid);
396 r = manager_get_session_from_creds(m, message, NULL, error, &session);
400 r = manager_get_session_by_pid(m, pid, &session);
405 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
408 p = session_bus_path(session);
412 return sd_bus_reply_method_return(message, "o", p);
415 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
416 _cleanup_free_ char *p = NULL;
417 Manager *m = userdata;
425 r = sd_bus_message_read(message, "u", &uid);
429 r = manager_get_user_from_creds(m, message, uid, error, &user);
433 p = user_bus_path(user);
437 return sd_bus_reply_method_return(message, "o", p);
440 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
441 _cleanup_free_ char *p = NULL;
442 Manager *m = userdata;
450 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
452 r = sd_bus_message_read(message, "u", &pid);
459 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
463 r = manager_get_user_by_pid(m, pid, &user);
467 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
468 "PID "PID_FMT" does not belong to any logged in user or lingering user",
472 p = user_bus_path(user);
476 return sd_bus_reply_method_return(message, "o", p);
479 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
480 _cleanup_free_ char *p = NULL;
481 Manager *m = userdata;
489 r = sd_bus_message_read(message, "s", &name);
493 r = manager_get_seat_from_creds(m, message, name, error, &seat);
497 p = seat_bus_path(seat);
501 return sd_bus_reply_method_return(message, "o", p);
504 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
505 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
506 Manager *m = userdata;
514 r = sd_bus_message_new_method_return(message, &reply);
518 r = sd_bus_message_open_container(reply, 'a', "(susso)");
522 HASHMAP_FOREACH(session, m->sessions, i) {
523 _cleanup_free_ char *p = NULL;
525 p = session_bus_path(session);
529 r = sd_bus_message_append(reply, "(susso)",
531 (uint32_t) session->user->uid,
533 session->seat ? session->seat->id : "",
539 r = sd_bus_message_close_container(reply);
543 return sd_bus_send(NULL, reply, NULL);
546 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
547 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
548 Manager *m = userdata;
556 r = sd_bus_message_new_method_return(message, &reply);
560 r = sd_bus_message_open_container(reply, 'a', "(uso)");
564 HASHMAP_FOREACH(user, m->users, i) {
565 _cleanup_free_ char *p = NULL;
567 p = user_bus_path(user);
571 r = sd_bus_message_append(reply, "(uso)",
572 (uint32_t) user->uid,
579 r = sd_bus_message_close_container(reply);
583 return sd_bus_send(NULL, reply, NULL);
586 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
587 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
588 Manager *m = userdata;
596 r = sd_bus_message_new_method_return(message, &reply);
600 r = sd_bus_message_open_container(reply, 'a', "(so)");
604 HASHMAP_FOREACH(seat, m->seats, i) {
605 _cleanup_free_ char *p = NULL;
607 p = seat_bus_path(seat);
611 r = sd_bus_message_append(reply, "(so)", seat->id, p);
616 r = sd_bus_message_close_container(reply);
620 return sd_bus_send(NULL, reply, NULL);
623 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
624 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
625 Manager *m = userdata;
626 Inhibitor *inhibitor;
633 r = sd_bus_message_new_method_return(message, &reply);
637 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
641 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
643 r = sd_bus_message_append(reply, "(ssssuu)",
644 strempty(inhibit_what_to_string(inhibitor->what)),
645 strempty(inhibitor->who),
646 strempty(inhibitor->why),
647 strempty(inhibit_mode_to_string(inhibitor->mode)),
648 (uint32_t) inhibitor->uid,
649 (uint32_t) inhibitor->pid);
654 r = sd_bus_message_close_container(reply);
658 return sd_bus_send(NULL, reply, NULL);
661 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
662 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
663 uint32_t audit_id = 0;
664 _cleanup_free_ char *unit = NULL;
665 _cleanup_free_ char *id = NULL;
666 Session *session = NULL;
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)
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 || 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);
795 * Check if we are already in a logind session. Or if we are in user@.service
796 * which is a special PAM session that avoids creating a logind session.
798 r = cg_pid_get_unit(leader, &unit);
801 if (hashmap_get(m->session_units, unit) ||
802 hashmap_get(m->user_units, unit))
803 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
806 * Old gdm and lightdm start the user-session on the same VT as
807 * the greeter session. But they destroy the greeter session
808 * after the user-session and want the user-session to take
809 * over the VT. We need to support this for
810 * backwards-compatibility, so make sure we allow new sessions
811 * on a VT that a greeter is running on. Furthermore, to allow
812 * re-logins, we have to allow a greeter to take over a used VT for
813 * the exact same reasons.
815 if (c != SESSION_GREETER &&
817 vtnr < m->seat0->position_count &&
818 m->seat0->positions[vtnr] &&
819 m->seat0->positions[vtnr]->class != SESSION_GREETER)
820 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
822 if (hashmap_size(m->sessions) >= m->sessions_max)
823 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
825 (void) audit_session_from_pid(leader, &audit_id);
826 if (audit_session_is_valid(audit_id)) {
827 /* Keep our session IDs and the audit session IDs in sync */
829 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
832 /* Wut? There's already a session by this name and we
833 * didn't find it above? Weird, then let's not trust
834 * the audit data and let's better register a new
836 if (hashmap_get(m->sessions, id)) {
837 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
838 audit_id = AUDIT_SESSION_INVALID;
848 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
851 } while (hashmap_get(m->sessions, id));
854 r = manager_add_user_by_uid(m, uid, &user);
858 r = manager_add_session(m, id, &session);
862 session_set_user(session, user);
864 session->leader = leader;
865 session->audit_id = audit_id;
868 session->remote = remote;
869 session->vtnr = vtnr;
872 session->tty = strdup(tty);
879 if (!isempty(display)) {
880 session->display = strdup(display);
881 if (!session->display) {
887 if (!isempty(remote_user)) {
888 session->remote_user = strdup(remote_user);
889 if (!session->remote_user) {
895 if (!isempty(remote_host)) {
896 session->remote_host = strdup(remote_host);
897 if (!session->remote_host) {
903 if (!isempty(service)) {
904 session->service = strdup(service);
905 if (!session->service) {
911 if (!isempty(desktop)) {
912 session->desktop = strdup(desktop);
913 if (!session->desktop) {
920 r = seat_attach_session(seat, session);
925 r = session_start(session);
929 session->create_message = sd_bus_message_ref(message);
931 #if 0 /// UNNEEDED by elogind
932 /* Now, let's wait until the slice unit and stuff got
933 * created. We send the reply back from
934 * session_send_create_reply(). */
936 /* We reply directly. */
938 r = session_send_create_reply(session, NULL);
947 session_add_to_gc_queue(session);
950 user_add_to_gc_queue(user);
955 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
956 Manager *m = userdata;
964 r = sd_bus_message_read(message, "s", &name);
968 r = manager_get_session_from_creds(m, message, name, error, &session);
972 r = session_release(session);
976 #if 1 /// elogind must queue this session
977 session_add_to_gc_queue(session);
979 return sd_bus_reply_method_return(message, NULL);
982 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
983 Manager *m = userdata;
991 r = sd_bus_message_read(message, "s", &name);
995 r = manager_get_session_from_creds(m, message, name, error, &session);
999 return bus_session_method_activate(message, session, error);
1002 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1003 const char *session_name, *seat_name;
1004 Manager *m = userdata;
1012 /* Same as ActivateSession() but refuses to work if
1013 * the seat doesn't match */
1015 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
1019 r = manager_get_session_from_creds(m, message, session_name, error, &session);
1023 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
1027 if (session->seat != seat)
1028 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
1030 r = session_activate(session);
1034 return sd_bus_reply_method_return(message, NULL);
1037 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1038 Manager *m = userdata;
1046 r = sd_bus_message_read(message, "s", &name);
1050 r = manager_get_session_from_creds(m, message, name, error, &session);
1054 return bus_session_method_lock(message, session, error);
1057 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1058 Manager *m = userdata;
1064 r = bus_verify_polkit_async(
1067 "org.freedesktop.login1.lock-sessions",
1071 &m->polkit_registry,
1076 return 1; /* Will call us back */
1078 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1082 return sd_bus_reply_method_return(message, NULL);
1085 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1087 Manager *m = userdata;
1094 r = sd_bus_message_read(message, "s", &name);
1098 r = manager_get_session_from_creds(m, message, name, error, &session);
1102 return bus_session_method_kill(message, session, error);
1105 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1106 Manager *m = userdata;
1114 r = sd_bus_message_read(message, "u", &uid);
1118 r = manager_get_user_from_creds(m, message, uid, error, &user);
1122 return bus_user_method_kill(message, user, error);
1125 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1126 Manager *m = userdata;
1134 r = sd_bus_message_read(message, "s", &name);
1138 r = manager_get_session_from_creds(m, message, name, error, &session);
1142 return bus_session_method_terminate(message, session, error);
1145 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1146 Manager *m = userdata;
1154 r = sd_bus_message_read(message, "u", &uid);
1158 r = manager_get_user_from_creds(m, message, uid, error, &user);
1162 return bus_user_method_terminate(message, user, error);
1165 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1166 Manager *m = userdata;
1174 r = sd_bus_message_read(message, "s", &name);
1178 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1182 return bus_seat_method_terminate(message, seat, error);
1185 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1186 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1187 _cleanup_free_ char *cc = NULL;
1188 Manager *m = userdata;
1189 int r, b, interactive;
1192 uint32_t uid, auth_uid;
1197 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1201 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
1202 SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1206 if (!uid_is_valid(uid)) {
1207 /* Note that we get the owner UID of the session or user unit,
1208 * not the actual client UID here! */
1209 r = sd_bus_creds_get_owner_uid(creds, &uid);
1214 /* owner_uid is racy, so for authorization we must use euid */
1215 r = sd_bus_creds_get_euid(creds, &auth_uid);
1222 return errno > 0 ? -errno : -ENOENT;
1224 r = bus_verify_polkit_async(
1227 uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
1228 "org.freedesktop.login1.set-user-linger",
1232 &m->polkit_registry,
1237 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1239 mkdir_p_label("/var/lib/elogind", 0755);
1241 r = mkdir_safe_label("/var/lib/elogind/linger", 0755, 0, 0, false);
1245 cc = cescape(pw->pw_name);
1249 path = strjoina("/var/lib/elogind/linger/", cc);
1257 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1264 if (r < 0 && errno != ENOENT)
1267 u = hashmap_get(m->users, UID_TO_PTR(uid));
1269 user_add_to_gc_queue(u);
1272 return sd_bus_reply_method_return(message, NULL);
1275 static int trigger_device(Manager *m, struct udev_device *d) {
1276 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1277 struct udev_list_entry *first, *item;
1282 e = udev_enumerate_new(m->udev);
1287 r = udev_enumerate_add_match_parent(e, d);
1292 r = udev_enumerate_scan_devices(e);
1296 first = udev_enumerate_get_list_entry(e);
1297 udev_list_entry_foreach(item, first) {
1298 _cleanup_free_ char *t = NULL;
1301 p = udev_list_entry_get_name(item);
1303 t = strappend(p, "/uevent");
1307 (void) write_string_file(t, "change", 0);
1313 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1314 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1315 _cleanup_free_ char *rule = NULL, *file = NULL;
1316 const char *id_for_seat;
1323 d = udev_device_new_from_syspath(m->udev, sysfs);
1327 if (!udev_device_has_tag(d, "seat"))
1330 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1334 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1337 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1340 mkdir_p_label("/etc/udev/rules.d", 0755);
1341 r = write_string_file_atomic_label(file, rule);
1345 return trigger_device(m, d);
1348 static int flush_devices(Manager *m) {
1349 _cleanup_closedir_ DIR *d;
1353 d = opendir("/etc/udev/rules.d");
1355 if (errno != ENOENT)
1356 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1360 FOREACH_DIRENT_ALL(de, d, break) {
1361 if (!dirent_is_file(de))
1364 if (!startswith(de->d_name, "72-seat-"))
1367 if (!endswith(de->d_name, ".rules"))
1370 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1371 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1375 return trigger_device(m, NULL);
1378 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1379 const char *sysfs, *seat;
1380 Manager *m = userdata;
1386 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1390 if (!path_startswith(sysfs, "/sys"))
1391 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1393 if (!seat_name_is_valid(seat))
1394 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1396 r = bus_verify_polkit_async(
1399 "org.freedesktop.login1.attach-device",
1403 &m->polkit_registry,
1408 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1410 r = attach_device(m, seat, sysfs);
1414 return sd_bus_reply_method_return(message, NULL);
1417 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1418 Manager *m = userdata;
1424 r = sd_bus_message_read(message, "b", &interactive);
1428 r = bus_verify_polkit_async(
1431 "org.freedesktop.login1.flush-devices",
1435 &m->polkit_registry,
1440 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1442 r = flush_devices(m);
1446 return sd_bus_reply_method_return(message, NULL);
1449 static int have_multiple_sessions(
1458 /* Check for other users' sessions. Greeter sessions do not
1459 * count, and non-login sessions do not count either. */
1460 HASHMAP_FOREACH(session, m->sessions, i)
1461 if (session->class == SESSION_USER &&
1462 session->user->uid != uid)
1468 #if 0 /// elogind has its own variant in elogind-dbus.c
1469 static int bus_manager_log_shutdown(
1471 const char *unit_name) {
1478 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1479 p = "MESSAGE=System is powering down";
1480 q = "SHUTDOWN=power-off";
1481 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1482 p = "MESSAGE=System is rebooting";
1483 q = "SHUTDOWN=reboot";
1484 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1485 p = "MESSAGE=System is halting";
1486 q = "SHUTDOWN=halt";
1487 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1488 p = "MESSAGE=System is rebooting with kexec";
1489 q = "SHUTDOWN=kexec";
1491 p = "MESSAGE=System is shutting down";
1495 if (isempty(m->wall_message))
1496 p = strjoina(p, ".");
1498 p = strjoina(p, " (", m->wall_message, ").");
1500 return log_struct(LOG_NOTICE,
1501 "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
1508 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1509 Manager *m = userdata;
1514 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1518 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1523 if (until <= now(CLOCK_MONOTONIC))
1526 /* We want to ignore the lid switch for a while after each
1527 * suspend, and after boot-up. Hence let's install a timer for
1528 * this. As long as the event source exists we ignore the lid
1531 if (m->lid_switch_ignore_event_source) {
1534 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1541 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1543 r = sd_event_add_time(
1545 &m->lid_switch_ignore_event_source,
1548 lid_switch_ignore_handler, m);
1553 #if 0 /// elogind-dbus.c needs to access this
1554 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1556 int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1559 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1560 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1561 [INHIBIT_SLEEP] = "PrepareForSleep"
1564 int active = _active;
1568 assert(w < _INHIBIT_WHAT_MAX);
1569 assert(signal_name[w]);
1571 return sd_bus_emit_signal(m->bus,
1572 "/org/freedesktop/login1",
1573 "org.freedesktop.login1.Manager",
1579 #if 0 /// elogind has its own variant in elogind-dbus.c
1580 static int execute_shutdown_or_sleep(
1583 const char *unit_name,
1584 sd_bus_error *error) {
1586 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1593 assert(w < _INHIBIT_WHAT_MAX);
1596 if (w == INHIBIT_SHUTDOWN)
1597 bus_manager_log_shutdown(m, unit_name);
1599 r = sd_bus_call_method(
1601 "org.freedesktop.systemd1",
1602 "/org/freedesktop/systemd1",
1603 "org.freedesktop.systemd1.Manager",
1607 "ss", unit_name, "replace-irreversibly");
1611 r = sd_bus_message_read(reply, "o", &p);
1621 m->action_unit = unit_name;
1622 free(m->action_job);
1626 /* Make sure the lid switch is ignored for a while */
1627 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1632 /* Tell people that they now may take a lock again */
1633 (void) send_prepare_for(m, w, false);
1638 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1640 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1641 Inhibitor *offending = NULL;
1646 if (manager->action_what == 0 || manager->action_job)
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 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1666 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1667 bus_error_message(&error, r));
1669 manager->action_unit = NULL;
1670 manager->action_what = 0;
1678 #if 0 /// elogind-dbus.c needs to access this
1679 static int manager_inhibit_timeout_handler(
1681 int manager_inhibit_timeout_handler(
1687 Manager *manager = userdata;
1691 assert(manager->inhibit_timeout_source == s);
1693 r = manager_dispatch_delayed(manager, true);
1694 return (r < 0) ? r : 0;
1697 #if 0 /// elogind has its own variant in elogind-dbus.c
1698 static int delay_shutdown_or_sleep(
1701 const char *unit_name) {
1708 assert(w < _INHIBIT_WHAT_MAX);
1711 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1713 if (m->inhibit_timeout_source) {
1714 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1716 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1718 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1720 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1722 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1723 timeout_val, 0, manager_inhibit_timeout_handler, m);
1728 m->action_unit = unit_name;
1735 #if 0 /// elogind has its own variant in elogind-dbus.c
1736 int bus_manager_shutdown_or_sleep_now_or_later(
1738 const char *unit_name,
1740 sd_bus_error *error) {
1748 assert(w <= _INHIBIT_WHAT_MAX);
1749 assert(!m->action_job);
1751 /* Tell everybody to prepare for shutdown/sleep */
1752 (void) send_prepare_for(m, w, true);
1755 m->inhibit_delay_max > 0 &&
1756 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1758 log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
1759 handle_action_to_string(action),
1760 delayed ? "" : "NOT ");
1762 /* Shutdown is delayed, keep in mind what we
1763 * want to do, and start a timeout */
1764 r = delay_shutdown_or_sleep(m, w, unit_name);
1766 /* Shutdown is not delayed, execute it
1768 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1774 #if 0 /// elogind-dbus.c needs to access this
1775 static int verify_shutdown_creds(
1777 int verify_shutdown_creds(
1780 sd_bus_message *message,
1784 const char *action_multiple_sessions,
1785 const char *action_ignore_inhibit,
1786 sd_bus_error *error) {
1788 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1789 bool multiple_sessions, blocked;
1796 assert(w <= _INHIBIT_WHAT_MAX);
1798 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1802 r = sd_bus_creds_get_euid(creds, &uid);
1806 r = have_multiple_sessions(m, uid);
1810 multiple_sessions = r > 0;
1811 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1813 if (multiple_sessions && action_multiple_sessions) {
1814 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1818 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1821 if (blocked && action_ignore_inhibit) {
1822 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1826 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1829 if (!multiple_sessions && !blocked && action) {
1830 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1834 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1840 #if 0 /// elogind has its own variant in elogind-dbus.c
1841 static int method_do_shutdown_or_sleep(
1843 sd_bus_message *message,
1844 const char *unit_name,
1847 const char *action_multiple_sessions,
1848 const char *action_ignore_inhibit,
1849 const char *sleep_verb,
1850 sd_bus_error *error) {
1858 assert(w <= _INHIBIT_WHAT_MAX);
1860 r = sd_bus_message_read(message, "b", &interactive);
1864 /* Don't allow multiple jobs being executed at the same time */
1866 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1869 r = can_sleep(sleep_verb);
1874 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1877 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1878 action_ignore_inhibit, error);
1879 log_debug_elogind("verify_shutdown_creds() returned %d", r);
1883 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1887 return sd_bus_reply_method_return(message, NULL);
1890 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1891 Manager *m = userdata;
1893 return method_do_shutdown_or_sleep(
1895 SPECIAL_POWEROFF_TARGET,
1897 "org.freedesktop.login1.power-off",
1898 "org.freedesktop.login1.power-off-multiple-sessions",
1899 "org.freedesktop.login1.power-off-ignore-inhibit",
1904 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1905 Manager *m = userdata;
1907 return method_do_shutdown_or_sleep(
1909 SPECIAL_REBOOT_TARGET,
1911 "org.freedesktop.login1.reboot",
1912 "org.freedesktop.login1.reboot-multiple-sessions",
1913 "org.freedesktop.login1.reboot-ignore-inhibit",
1918 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1919 Manager *m = userdata;
1921 return method_do_shutdown_or_sleep(
1923 SPECIAL_HALT_TARGET,
1925 "org.freedesktop.login1.halt",
1926 "org.freedesktop.login1.halt-multiple-sessions",
1927 "org.freedesktop.login1.halt-ignore-inhibit",
1932 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1933 Manager *m = userdata;
1935 return method_do_shutdown_or_sleep(
1937 SPECIAL_SUSPEND_TARGET,
1939 "org.freedesktop.login1.suspend",
1940 "org.freedesktop.login1.suspend-multiple-sessions",
1941 "org.freedesktop.login1.suspend-ignore-inhibit",
1946 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1947 Manager *m = userdata;
1949 return method_do_shutdown_or_sleep(
1951 SPECIAL_HIBERNATE_TARGET,
1953 "org.freedesktop.login1.hibernate",
1954 "org.freedesktop.login1.hibernate-multiple-sessions",
1955 "org.freedesktop.login1.hibernate-ignore-inhibit",
1960 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1961 Manager *m = userdata;
1963 return method_do_shutdown_or_sleep(
1965 SPECIAL_HYBRID_SLEEP_TARGET,
1967 "org.freedesktop.login1.hibernate",
1968 "org.freedesktop.login1.hibernate-multiple-sessions",
1969 "org.freedesktop.login1.hibernate-ignore-inhibit",
1975 static int nologin_timeout_handler(
1980 Manager *m = userdata;
1982 log_info("Creating /run/nologin, blocking further logins...");
1985 create_shutdown_run_nologin_or_warn() >= 0;
1990 static int update_schedule_file(Manager *m) {
1991 _cleanup_free_ char *temp_path = NULL;
1992 _cleanup_fclose_ FILE *f = NULL;
1997 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, false);
1999 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
2001 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
2003 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
2005 (void) fchmod(fileno(f), 0644);
2011 m->scheduled_shutdown_timeout,
2012 m->enable_wall_messages,
2013 m->scheduled_shutdown_type);
2015 if (!isempty(m->wall_message)) {
2016 _cleanup_free_ char *t;
2018 t = cescape(m->wall_message);
2024 fprintf(f, "WALL_MESSAGE=%s\n", t);
2027 r = fflush_and_check(f);
2031 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
2039 (void) unlink(temp_path);
2040 (void) unlink("/run/systemd/shutdown/scheduled");
2042 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
2045 static void reset_scheduled_shutdown(Manager *m) {
2048 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2049 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2050 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2052 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2053 m->scheduled_shutdown_timeout = 0;
2054 m->shutdown_dry_run = false;
2056 if (m->unlink_nologin) {
2057 (void) unlink_or_warn("/run/nologin");
2058 m->unlink_nologin = false;
2061 (void) unlink("/run/systemd/shutdown/scheduled");
2064 #if 0 /// elogind has its own variant in elogind-dbus.c
2065 static int manager_scheduled_shutdown_handler(
2070 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2071 Manager *m = userdata;
2077 if (isempty(m->scheduled_shutdown_type))
2080 if (streq(m->scheduled_shutdown_type, "poweroff"))
2081 target = SPECIAL_POWEROFF_TARGET;
2082 else if (streq(m->scheduled_shutdown_type, "reboot"))
2083 target = SPECIAL_REBOOT_TARGET;
2084 else if (streq(m->scheduled_shutdown_type, "halt"))
2085 target = SPECIAL_HALT_TARGET;
2087 assert_not_reached("unexpected shutdown type");
2089 /* Don't allow multiple jobs being executed at the same time */
2090 if (m->action_what) {
2092 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
2096 if (m->shutdown_dry_run) {
2097 /* We do not process delay inhibitors here. Otherwise, we
2098 * would have to be considered "in progress" (like the check
2099 * above) for some seconds after our admin has seen the final
2102 bus_manager_log_shutdown(m, target);
2103 log_info("Running in dry run, suppressing action.");
2104 reset_scheduled_shutdown(m);
2109 r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
2111 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2118 reset_scheduled_shutdown(m);
2123 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2124 Manager *m = userdata;
2125 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2126 const char *action_multiple_sessions = NULL;
2127 const char *action_ignore_inhibit = NULL;
2128 const char *action = NULL;
2132 bool dry_run = false;
2137 log_debug_elogind("%s called", __FUNCTION__);
2138 r = sd_bus_message_read(message, "st", &type, &elapse);
2142 if (startswith(type, "dry-")) {
2147 if (streq(type, "poweroff")) {
2148 action = "org.freedesktop.login1.power-off";
2149 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2150 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2151 } else if (streq(type, "reboot")) {
2152 action = "org.freedesktop.login1.reboot";
2153 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2154 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2155 } else if (streq(type, "halt")) {
2156 action = "org.freedesktop.login1.halt";
2157 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2158 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
2160 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2162 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2163 action, action_multiple_sessions, action_ignore_inhibit, error);
2167 if (m->scheduled_shutdown_timeout_source) {
2168 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2170 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2172 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2174 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2176 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2177 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2179 return log_error_errno(r, "sd_event_add_time() failed: %m");
2182 r = free_and_strdup(&m->scheduled_shutdown_type, type);
2184 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2188 m->shutdown_dry_run = dry_run;
2190 if (m->nologin_timeout_source) {
2191 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2193 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2195 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2197 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2199 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2200 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2202 return log_error_errno(r, "sd_event_add_time() failed: %m");
2205 m->scheduled_shutdown_timeout = elapse;
2207 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2209 const char *tty = NULL;
2211 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2212 (void) sd_bus_creds_get_tty(creds, &tty);
2214 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2216 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2221 r = manager_setup_wall_message_timer(m);
2225 r = update_schedule_file(m);
2229 return sd_bus_reply_method_return(message, NULL);
2232 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2233 Manager *m = userdata;
2235 #if 1 /// elogind needs to construct the message to allow extra wall messages
2236 _cleanup_free_ char *l = NULL;
2242 log_debug_elogind("%s called", __FUNCTION__);
2243 cancelled = m->scheduled_shutdown_type != NULL;
2244 reset_scheduled_shutdown(m);
2246 if (cancelled && m->enable_wall_messages) {
2247 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2248 const char *tty = NULL;
2252 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2254 (void) sd_bus_creds_get_uid(creds, &uid);
2255 (void) sd_bus_creds_get_tty(creds, &tty);
2258 #if 0 /// elogind wants to allow extra cancellation messages
2259 utmp_wall("The system shutdown has been cancelled",
2260 uid_to_name(uid), tty, logind_wall_tty_filter, m);
2262 r = asprintf(&l, "%s%sThe system shutdown has been cancelled!",
2263 strempty(m->wall_message),
2264 isempty(m->wall_message) ? "" : "\n");
2270 utmp_wall(l, uid_to_name(uid), tty, logind_wall_tty_filter, m);
2274 return sd_bus_reply_method_return(message, "b", cancelled);
2277 static int method_can_shutdown_or_sleep(
2279 sd_bus_message *message,
2282 const char *action_multiple_sessions,
2283 const char *action_ignore_inhibit,
2284 const char *sleep_verb,
2285 sd_bus_error *error) {
2287 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2288 bool multiple_sessions, challenge, blocked;
2289 const char *result = NULL;
2296 assert(w <= _INHIBIT_WHAT_MAX);
2298 assert(action_multiple_sessions);
2299 assert(action_ignore_inhibit);
2302 #if 0 /// elogind needs to have the manager being passed
2303 r = can_sleep(sleep_verb);
2305 r = can_sleep(m, sleep_verb);
2310 return sd_bus_reply_method_return(message, "s", "na");
2313 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2317 r = sd_bus_creds_get_euid(creds, &uid);
2321 r = have_multiple_sessions(m, uid);
2325 multiple_sessions = r > 0;
2326 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2328 if (multiple_sessions) {
2329 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2336 result = "challenge";
2342 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2346 if (r > 0 && !result)
2348 else if (challenge && (!result || streq(result, "yes")))
2349 result = "challenge";
2354 if (!multiple_sessions && !blocked) {
2355 /* If neither inhibit nor multiple sessions
2356 * apply then just check the normal policy */
2358 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2365 result = "challenge";
2370 return sd_bus_reply_method_return(message, "s", result);
2373 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2374 Manager *m = userdata;
2376 return method_can_shutdown_or_sleep(
2379 "org.freedesktop.login1.power-off",
2380 "org.freedesktop.login1.power-off-multiple-sessions",
2381 "org.freedesktop.login1.power-off-ignore-inhibit",
2386 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2387 Manager *m = userdata;
2389 return method_can_shutdown_or_sleep(
2392 "org.freedesktop.login1.reboot",
2393 "org.freedesktop.login1.reboot-multiple-sessions",
2394 "org.freedesktop.login1.reboot-ignore-inhibit",
2399 static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2400 Manager *m = userdata;
2402 return method_can_shutdown_or_sleep(
2405 "org.freedesktop.login1.halt",
2406 "org.freedesktop.login1.halt-multiple-sessions",
2407 "org.freedesktop.login1.halt-ignore-inhibit",
2412 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2413 Manager *m = userdata;
2415 return method_can_shutdown_or_sleep(
2418 "org.freedesktop.login1.suspend",
2419 "org.freedesktop.login1.suspend-multiple-sessions",
2420 "org.freedesktop.login1.suspend-ignore-inhibit",
2425 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2426 Manager *m = userdata;
2428 return method_can_shutdown_or_sleep(
2431 "org.freedesktop.login1.hibernate",
2432 "org.freedesktop.login1.hibernate-multiple-sessions",
2433 "org.freedesktop.login1.hibernate-ignore-inhibit",
2438 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2439 Manager *m = userdata;
2441 return method_can_shutdown_or_sleep(
2444 "org.freedesktop.login1.hibernate",
2445 "org.freedesktop.login1.hibernate-multiple-sessions",
2446 "org.freedesktop.login1.hibernate-ignore-inhibit",
2451 static int property_get_reboot_to_firmware_setup(
2454 const char *interface,
2455 const char *property,
2456 sd_bus_message *reply,
2458 sd_bus_error *error) {
2459 #if 0 /// elogind does not support EFI
2466 r = efi_get_reboot_to_firmware();
2467 if (r < 0 && r != -EOPNOTSUPP)
2468 log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
2470 return sd_bus_message_append(reply, "b", r > 0);
2472 return sd_bus_message_append(reply, "b", false);
2476 static int method_set_reboot_to_firmware_setup(
2477 sd_bus_message *message,
2479 sd_bus_error *error) {
2482 Manager *m = userdata;
2487 r = sd_bus_message_read(message, "b", &b);
2491 r = bus_verify_polkit_async(message,
2493 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2497 &m->polkit_registry,
2502 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2504 #if 0 /// elogind does not support EFI
2505 r = efi_set_reboot_to_firmware(b);
2510 return sd_bus_reply_method_return(message, NULL);
2513 static int method_can_reboot_to_firmware_setup(
2514 sd_bus_message *message,
2516 sd_bus_error *error) {
2518 #if 0 /// elogind does not support EFI
2522 Manager *m = userdata;
2527 r = efi_reboot_to_firmware_supported();
2529 if (r != -EOPNOTSUPP)
2530 log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m");
2532 return sd_bus_reply_method_return(message, "s", "na");
2535 r = bus_test_polkit(message,
2537 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2548 result = "challenge";
2552 return sd_bus_reply_method_return(message, "s", result);
2554 return sd_bus_reply_method_return(message, "s", "no");
2558 static int method_set_wall_message(
2559 sd_bus_message *message,
2561 sd_bus_error *error) {
2564 Manager *m = userdata;
2566 int enable_wall_messages;
2571 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2575 #if 0 /// elogind only calls this for shutdown/reboot, which already needs authorization.
2576 r = bus_verify_polkit_async(message,
2578 "org.freedesktop.login1.set-wall-message",
2582 &m->polkit_registry,
2587 return 1; /* Will call us back */
2590 r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
2594 m->enable_wall_messages = enable_wall_messages;
2596 return sd_bus_reply_method_return(message, NULL);
2599 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2600 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2601 const char *who, *why, *what, *mode;
2602 _cleanup_free_ char *id = NULL;
2603 _cleanup_close_ int fifo_fd = -1;
2604 Manager *m = userdata;
2605 Inhibitor *i = NULL;
2615 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2619 w = inhibit_what_from_string(what);
2621 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2623 mm = inhibit_mode_from_string(mode);
2625 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2627 /* Delay is only supported for shutdown/sleep */
2628 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2629 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2631 /* Don't allow taking delay locks while we are already
2632 * executing the operation. We shouldn't create the impression
2633 * that the lock was successful if the machine is about to go
2634 * down/suspend any moment. */
2635 if (m->action_what & w)
2636 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2638 r = bus_verify_polkit_async(
2641 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2642 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2643 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2644 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2645 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2646 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2647 "org.freedesktop.login1.inhibit-handle-lid-switch",
2651 &m->polkit_registry,
2656 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2658 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2662 r = sd_bus_creds_get_euid(creds, &uid);
2666 r = sd_bus_creds_get_pid(creds, &pid);
2670 if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
2671 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
2676 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2679 } while (hashmap_get(m->inhibitors, id));
2681 r = manager_add_inhibitor(m, id, &i);
2689 i->why = strdup(why);
2690 i->who = strdup(who);
2692 if (!i->why || !i->who) {
2697 fifo_fd = inhibitor_create_fifo(i);
2705 return sd_bus_reply_method_return(message, "h", fifo_fd);
2714 const sd_bus_vtable manager_vtable[] = {
2715 SD_BUS_VTABLE_START(0),
2717 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2718 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2720 #if 0 /// UNNEEDED by elogind
2721 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2723 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2724 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2725 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2726 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2727 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2728 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2729 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2730 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2731 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2732 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2733 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2734 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2735 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2736 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2737 SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
2738 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2739 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2740 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2741 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2742 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2743 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2744 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2745 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2746 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
2747 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
2748 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
2749 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
2750 SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
2751 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
2752 SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2754 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2755 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2756 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2757 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2758 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2759 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2760 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2761 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2762 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2763 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2764 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2765 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2766 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2767 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2768 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2769 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2770 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2771 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2772 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2773 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2774 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2775 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2776 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2777 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2778 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2779 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2780 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2781 SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2782 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2783 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2784 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2785 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2786 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2787 SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2788 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2789 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2790 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2791 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2792 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2793 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2794 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2795 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2796 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2798 SD_BUS_SIGNAL("SessionNew", "so", 0),
2799 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2800 SD_BUS_SIGNAL("UserNew", "uo", 0),
2801 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2802 SD_BUS_SIGNAL("SeatNew", "so", 0),
2803 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2804 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2805 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2810 #if 0 /// UNNEEDED by elogind
2811 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2820 if (streq(result, "done"))
2821 r = session_send_create_reply(s, NULL);
2823 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
2825 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2826 r = session_send_create_reply(s, &e);
2832 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2833 const char *path, *result, *unit;
2834 Manager *m = userdata;
2843 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2845 bus_log_parse_error(r);
2849 if (m->action_job && streq(m->action_job, path)) {
2850 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2852 /* Tell people that they now may take a lock again */
2853 (void) send_prepare_for(m, m->action_what, false);
2855 m->action_job = mfree(m->action_job);
2856 m->action_unit = NULL;
2861 session = hashmap_get(m->session_units, unit);
2862 if (session && streq_ptr(path, session->scope_job)) {
2863 session->scope_job = mfree(session->scope_job);
2864 session_jobs_reply(session, unit, result);
2866 session_save(session);
2867 user_save(session->user);
2868 session_add_to_gc_queue(session);
2871 user = hashmap_get(m->user_units, unit);
2873 (streq_ptr(path, user->service_job) ||
2874 streq_ptr(path, user->slice_job))) {
2876 if (streq_ptr(path, user->service_job))
2877 user->service_job = mfree(user->service_job);
2879 if (streq_ptr(path, user->slice_job))
2880 user->slice_job = mfree(user->slice_job);
2882 LIST_FOREACH(sessions_by_user, session, user->sessions)
2883 session_jobs_reply(session, unit, result);
2886 user_add_to_gc_queue(user);
2892 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2893 const char *path, *unit;
2894 Manager *m = userdata;
2902 r = sd_bus_message_read(message, "so", &unit, &path);
2904 bus_log_parse_error(r);
2908 session = hashmap_get(m->session_units, unit);
2910 session_add_to_gc_queue(session);
2912 user = hashmap_get(m->user_units, unit);
2914 user_add_to_gc_queue(user);
2919 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2920 _cleanup_free_ char *unit = NULL;
2921 Manager *m = userdata;
2930 path = sd_bus_message_get_path(message);
2934 r = unit_name_from_dbus_path(path, &unit);
2935 if (r == -EINVAL) /* not a unit */
2942 session = hashmap_get(m->session_units, unit);
2944 session_add_to_gc_queue(session);
2946 user = hashmap_get(m->user_units, unit);
2948 user_add_to_gc_queue(user);
2953 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2954 Manager *m = userdata;
2962 r = sd_bus_message_read(message, "b", &b);
2964 bus_log_parse_error(r);
2971 /* systemd finished reloading, let's recheck all our sessions */
2972 log_debug("System manager has been reloaded, rechecking sessions...");
2974 HASHMAP_FOREACH(session, m->sessions, i)
2975 session_add_to_gc_queue(session);
2981 int manager_send_changed(Manager *manager, const char *property, ...) {
2986 l = strv_from_stdarg_alloca(property);
2988 return sd_bus_emit_properties_changed_strv(
2990 "/org/freedesktop/login1",
2991 "org.freedesktop.login1.Manager",
2995 #if 0 /// UNNEEDED by elogind
2996 static int strdup_job(sd_bus_message *reply, char **job) {
3001 r = sd_bus_message_read(reply, "o", &j);
3013 int manager_start_slice(
3016 const char *description,
3020 sd_bus_error *error,
3023 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3030 r = sd_bus_message_new_method_call(
3033 "org.freedesktop.systemd1",
3034 "/org/freedesktop/systemd1",
3035 "org.freedesktop.systemd1.Manager",
3036 "StartTransientUnit");
3040 r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
3044 r = sd_bus_message_open_container(m, 'a', "(sv)");
3048 if (!isempty(description)) {
3049 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3054 if (!isempty(after)) {
3055 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3060 if (!isempty(after2)) {
3061 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3066 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3070 r = sd_bus_message_close_container(m);
3074 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3078 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3082 return strdup_job(reply, job);
3085 int manager_start_scope(
3090 const char *description,
3094 sd_bus_error *error,
3097 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3105 r = sd_bus_message_new_method_call(
3108 "org.freedesktop.systemd1",
3109 "/org/freedesktop/systemd1",
3110 "org.freedesktop.systemd1.Manager",
3111 "StartTransientUnit");
3115 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3119 r = sd_bus_message_open_container(m, 'a', "(sv)");
3123 if (!isempty(slice)) {
3124 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3129 if (!isempty(description)) {
3130 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3135 if (!isempty(after)) {
3136 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3141 if (!isempty(after2)) {
3142 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3147 /* cgroup empty notification is not available in containers
3148 * currently. To make this less problematic, let's shorten the
3149 * stop timeout for sessions, so that we don't wait
3152 /* Make sure that the session shells are terminated with
3153 * SIGHUP since bash and friends tend to ignore SIGTERM */
3154 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3158 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3162 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3166 r = sd_bus_message_close_container(m);
3170 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3174 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3178 return strdup_job(reply, job);
3181 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3182 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3189 r = sd_bus_call_method(
3191 "org.freedesktop.systemd1",
3192 "/org/freedesktop/systemd1",
3193 "org.freedesktop.systemd1.Manager",
3197 "ss", unit, "replace");
3201 return strdup_job(reply, job);
3204 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3205 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3212 r = sd_bus_call_method(
3214 "org.freedesktop.systemd1",
3215 "/org/freedesktop/systemd1",
3216 "org.freedesktop.systemd1.Manager",
3220 "ss", unit, "fail");
3222 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3223 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3226 sd_bus_error_free(error);
3233 return strdup_job(reply, job);
3236 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3237 _cleanup_free_ char *path = NULL;
3243 path = unit_dbus_path_from_name(scope);
3247 r = sd_bus_call_method(
3249 "org.freedesktop.systemd1",
3251 "org.freedesktop.systemd1.Scope",
3257 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3258 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3259 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3260 sd_bus_error_free(error);
3270 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3274 return sd_bus_call_method(
3276 "org.freedesktop.systemd1",
3277 "/org/freedesktop/systemd1",
3278 "org.freedesktop.systemd1.Manager",
3282 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3285 int manager_unit_is_active(Manager *manager, const char *unit) {
3286 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3287 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3288 _cleanup_free_ char *path = NULL;
3295 path = unit_dbus_path_from_name(unit);
3299 r = sd_bus_get_property(
3301 "org.freedesktop.systemd1",
3303 "org.freedesktop.systemd1.Unit",
3309 /* systemd might have droppped off momentarily, let's
3310 * not make this an error */
3311 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3312 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3315 /* If the unit is already unloaded then it's not
3317 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3318 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3324 r = sd_bus_message_read(reply, "s", &state);
3328 return !streq(state, "inactive") && !streq(state, "failed");
3331 int manager_job_is_active(Manager *manager, const char *path) {
3332 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3333 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3339 r = sd_bus_get_property(
3341 "org.freedesktop.systemd1",
3343 "org.freedesktop.systemd1.Job",
3349 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3350 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3353 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3359 /* We don't actually care about the state really. The fact
3360 * that we could read the job state is enough for us */