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 "selinux-util.h"
45 #include "sleep-config.h"
46 //#include "special.h"
48 #include "terminal-util.h"
49 #include "udev-util.h"
50 #include "unit-name.h"
51 #include "user-util.h"
52 #include "utmp-wtmp.h"
54 /// Additional includes needed by elogind
55 #include "elogind-dbus.h"
56 static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
58 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
63 /* Get client login session. This is not what you are looking for these days,
64 * as apps may instead belong to a user service unit. This includes terminal
65 * emulators and hence command-line apps. */
66 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
70 r = sd_bus_creds_get_session(creds, &name);
76 session = hashmap_get(m->sessions, name);
84 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
85 "Caller does not belong to any known session");
88 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
96 return get_sender_session(m, message, error, ret);
98 session = hashmap_get(m->sessions, name);
100 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
106 static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
108 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
113 /* Note that we get the owner UID of the session, not the actual client UID here! */
114 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
118 r = sd_bus_creds_get_owner_uid(creds, &uid);
124 user = hashmap_get(m->users, UID_TO_PTR(uid));
132 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "Caller does not belong to any logged in user or lingering user");
135 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
142 if (!uid_is_valid(uid))
143 return get_sender_user(m, message, error, ret);
145 user = hashmap_get(m->users, UID_TO_PTR(uid));
147 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "User ID "UID_FMT" is not logged in or lingering", uid);
153 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
164 r = manager_get_session_from_creds(m, message, NULL, error, &session);
168 seat = session->seat;
170 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
172 seat = hashmap_get(m->seats, name);
174 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
181 static int property_get_idle_hint(
184 const char *interface,
185 const char *property,
186 sd_bus_message *reply,
188 sd_bus_error *error) {
190 Manager *m = userdata;
196 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
199 static int property_get_idle_since_hint(
202 const char *interface,
203 const char *property,
204 sd_bus_message *reply,
206 sd_bus_error *error) {
208 Manager *m = userdata;
209 dual_timestamp t = DUAL_TIMESTAMP_NULL;
215 manager_get_idle_hint(m, &t);
217 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
220 static int property_get_inhibited(
223 const char *interface,
224 const char *property,
225 sd_bus_message *reply,
227 sd_bus_error *error) {
229 Manager *m = userdata;
236 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
238 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
241 static int property_get_preparing(
244 const char *interface,
245 const char *property,
246 sd_bus_message *reply,
248 sd_bus_error *error) {
250 Manager *m = userdata;
257 if (streq(property, "PreparingForShutdown"))
258 b = !!(m->action_what & INHIBIT_SHUTDOWN);
260 b = !!(m->action_what & INHIBIT_SLEEP);
262 return sd_bus_message_append(reply, "b", b);
265 static int property_get_scheduled_shutdown(
268 const char *interface,
269 const char *property,
270 sd_bus_message *reply,
272 sd_bus_error *error) {
274 Manager *m = userdata;
281 r = sd_bus_message_open_container(reply, 'r', "st");
285 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
289 return sd_bus_message_close_container(reply);
292 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
294 static int property_get_docked(
297 const char *interface,
298 const char *property,
299 sd_bus_message *reply,
301 sd_bus_error *error) {
303 Manager *m = userdata;
309 return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
312 static int property_get_current_sessions(
315 const char *interface,
316 const char *property,
317 sd_bus_message *reply,
319 sd_bus_error *error) {
321 Manager *m = userdata;
327 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
330 static int property_get_current_inhibitors(
333 const char *interface,
334 const char *property,
335 sd_bus_message *reply,
337 sd_bus_error *error) {
339 Manager *m = userdata;
345 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
348 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
349 _cleanup_free_ char *p = NULL;
350 Manager *m = userdata;
358 r = sd_bus_message_read(message, "s", &name);
362 r = manager_get_session_from_creds(m, message, name, error, &session);
366 p = session_bus_path(session);
370 return sd_bus_reply_method_return(message, "o", p);
373 /* Get login session of a process. This is not what you are looking for these days,
374 * as apps may instead belong to a user service unit. This includes terminal
375 * emulators and hence command-line apps. */
376 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
377 _cleanup_free_ char *p = NULL;
378 Session *session = NULL;
379 Manager *m = userdata;
386 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
388 r = sd_bus_message_read(message, "u", &pid);
395 r = manager_get_session_from_creds(m, message, NULL, error, &session);
399 r = manager_get_session_by_pid(m, pid, &session);
404 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
407 p = session_bus_path(session);
411 return sd_bus_reply_method_return(message, "o", p);
414 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
415 _cleanup_free_ char *p = NULL;
416 Manager *m = userdata;
424 r = sd_bus_message_read(message, "u", &uid);
428 r = manager_get_user_from_creds(m, message, uid, error, &user);
432 p = user_bus_path(user);
436 return sd_bus_reply_method_return(message, "o", p);
439 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
440 _cleanup_free_ char *p = NULL;
441 Manager *m = userdata;
449 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
451 r = sd_bus_message_read(message, "u", &pid);
458 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
462 r = manager_get_user_by_pid(m, pid, &user);
466 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
467 "PID "PID_FMT" does not belong to any logged in user or lingering user",
471 p = user_bus_path(user);
475 return sd_bus_reply_method_return(message, "o", p);
478 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
479 _cleanup_free_ char *p = NULL;
480 Manager *m = userdata;
488 r = sd_bus_message_read(message, "s", &name);
492 r = manager_get_seat_from_creds(m, message, name, error, &seat);
496 p = seat_bus_path(seat);
500 return sd_bus_reply_method_return(message, "o", p);
503 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
504 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
505 Manager *m = userdata;
513 r = sd_bus_message_new_method_return(message, &reply);
517 r = sd_bus_message_open_container(reply, 'a', "(susso)");
521 HASHMAP_FOREACH(session, m->sessions, i) {
522 _cleanup_free_ char *p = NULL;
524 p = session_bus_path(session);
528 r = sd_bus_message_append(reply, "(susso)",
530 (uint32_t) session->user->uid,
532 session->seat ? session->seat->id : "",
538 r = sd_bus_message_close_container(reply);
542 return sd_bus_send(NULL, reply, NULL);
545 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
546 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
547 Manager *m = userdata;
555 r = sd_bus_message_new_method_return(message, &reply);
559 r = sd_bus_message_open_container(reply, 'a', "(uso)");
563 HASHMAP_FOREACH(user, m->users, i) {
564 _cleanup_free_ char *p = NULL;
566 p = user_bus_path(user);
570 r = sd_bus_message_append(reply, "(uso)",
571 (uint32_t) user->uid,
578 r = sd_bus_message_close_container(reply);
582 return sd_bus_send(NULL, reply, NULL);
585 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
586 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
587 Manager *m = userdata;
595 r = sd_bus_message_new_method_return(message, &reply);
599 r = sd_bus_message_open_container(reply, 'a', "(so)");
603 HASHMAP_FOREACH(seat, m->seats, i) {
604 _cleanup_free_ char *p = NULL;
606 p = seat_bus_path(seat);
610 r = sd_bus_message_append(reply, "(so)", seat->id, p);
615 r = sd_bus_message_close_container(reply);
619 return sd_bus_send(NULL, reply, NULL);
622 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
623 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
624 Manager *m = userdata;
625 Inhibitor *inhibitor;
632 r = sd_bus_message_new_method_return(message, &reply);
636 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
640 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
642 r = sd_bus_message_append(reply, "(ssssuu)",
643 strempty(inhibit_what_to_string(inhibitor->what)),
644 strempty(inhibitor->who),
645 strempty(inhibitor->why),
646 strempty(inhibit_mode_to_string(inhibitor->mode)),
647 (uint32_t) inhibitor->uid,
648 (uint32_t) inhibitor->pid);
653 r = sd_bus_message_close_container(reply);
657 return sd_bus_send(NULL, reply, NULL);
660 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
661 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
662 uint32_t audit_id = 0;
663 _cleanup_free_ char *id = NULL;
664 Session *session = NULL;
665 Manager *m = userdata;
679 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
680 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
682 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
686 if (!uid_is_valid(uid))
687 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
688 if (leader < 0 || leader == 1)
689 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
692 t = _SESSION_TYPE_INVALID;
694 t = session_type_from_string(type);
696 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
700 c = _SESSION_CLASS_INVALID;
702 c = session_class_from_string(class);
704 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
707 if (isempty(desktop))
710 if (!string_is_safe(desktop))
711 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
717 seat = hashmap_get(m->seats, cseat);
719 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
722 if (tty_is_vc(tty)) {
727 else if (seat != m->seat0)
728 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);
730 v = vtnr_from_tty(tty);
732 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
736 else if (vtnr != (uint32_t) v)
737 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
739 } else if (tty_is_console(tty)) {
743 else if (seat != m->seat0)
744 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
747 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
751 if (seat_has_vts(seat)) {
752 if (!vtnr || vtnr > 63)
753 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
756 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
760 r = sd_bus_message_enter_container(message, 'a', "(sv)");
764 if (t == _SESSION_TYPE_INVALID) {
765 if (!isempty(display))
767 else if (!isempty(tty))
770 t = SESSION_UNSPECIFIED;
773 if (c == _SESSION_CLASS_INVALID) {
774 if (t == SESSION_UNSPECIFIED)
775 c = SESSION_BACKGROUND;
781 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
783 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
787 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
792 r = manager_get_session_by_pid(m, leader, NULL);
794 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
797 * Old gdm and lightdm start the user-session on the same VT as
798 * the greeter session. But they destroy the greeter session
799 * after the user-session and want the user-session to take
800 * over the VT. We need to support this for
801 * backwards-compatibility, so make sure we allow new sessions
802 * on a VT that a greeter is running on. Furthermore, to allow
803 * re-logins, we have to allow a greeter to take over a used VT for
804 * the exact same reasons.
806 if (c != SESSION_GREETER &&
808 vtnr < m->seat0->position_count &&
809 m->seat0->positions[vtnr] &&
810 m->seat0->positions[vtnr]->class != SESSION_GREETER)
811 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
813 if (hashmap_size(m->sessions) >= m->sessions_max)
814 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
816 (void) audit_session_from_pid(leader, &audit_id);
817 if (audit_session_is_valid(audit_id)) {
818 /* Keep our session IDs and the audit session IDs in sync */
820 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
823 /* Wut? There's already a session by this name and we
824 * didn't find it above? Weird, then let's not trust
825 * the audit data and let's better register a new
827 if (hashmap_get(m->sessions, id)) {
828 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
829 audit_id = AUDIT_SESSION_INVALID;
839 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
842 } while (hashmap_get(m->sessions, id));
845 r = manager_add_user_by_uid(m, uid, &user);
849 r = manager_add_session(m, id, &session);
853 session_set_user(session, user);
855 session->leader = leader;
856 session->audit_id = audit_id;
859 session->remote = remote;
860 session->vtnr = vtnr;
863 session->tty = strdup(tty);
870 if (!isempty(display)) {
871 session->display = strdup(display);
872 if (!session->display) {
878 if (!isempty(remote_user)) {
879 session->remote_user = strdup(remote_user);
880 if (!session->remote_user) {
886 if (!isempty(remote_host)) {
887 session->remote_host = strdup(remote_host);
888 if (!session->remote_host) {
894 if (!isempty(service)) {
895 session->service = strdup(service);
896 if (!session->service) {
902 if (!isempty(desktop)) {
903 session->desktop = strdup(desktop);
904 if (!session->desktop) {
911 r = seat_attach_session(seat, session);
916 r = session_start(session);
920 session->create_message = sd_bus_message_ref(message);
922 #if 0 /// UNNEEDED by elogind
923 /* Now, let's wait until the slice unit and stuff got
924 * created. We send the reply back from
925 * session_send_create_reply(). */
927 /* We reply directly. */
929 r = session_send_create_reply(session, NULL);
938 session_add_to_gc_queue(session);
941 user_add_to_gc_queue(user);
946 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
947 Manager *m = userdata;
955 r = sd_bus_message_read(message, "s", &name);
959 r = manager_get_session_from_creds(m, message, name, error, &session);
963 r = session_release(session);
967 #if 1 /// elogind must queue this session
968 session_add_to_gc_queue(session);
970 return sd_bus_reply_method_return(message, NULL);
973 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
974 Manager *m = userdata;
982 r = sd_bus_message_read(message, "s", &name);
986 r = manager_get_session_from_creds(m, message, name, error, &session);
990 return bus_session_method_activate(message, session, error);
993 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
994 const char *session_name, *seat_name;
995 Manager *m = userdata;
1003 /* Same as ActivateSession() but refuses to work if
1004 * the seat doesn't match */
1006 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
1010 r = manager_get_session_from_creds(m, message, session_name, error, &session);
1014 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
1018 if (session->seat != seat)
1019 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
1021 r = session_activate(session);
1025 return sd_bus_reply_method_return(message, NULL);
1028 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1029 Manager *m = userdata;
1037 r = sd_bus_message_read(message, "s", &name);
1041 r = manager_get_session_from_creds(m, message, name, error, &session);
1045 return bus_session_method_lock(message, session, error);
1048 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1049 Manager *m = userdata;
1055 r = bus_verify_polkit_async(
1058 "org.freedesktop.login1.lock-sessions",
1062 &m->polkit_registry,
1067 return 1; /* Will call us back */
1069 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1073 return sd_bus_reply_method_return(message, NULL);
1076 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1078 Manager *m = userdata;
1085 r = sd_bus_message_read(message, "s", &name);
1089 r = manager_get_session_from_creds(m, message, name, error, &session);
1093 return bus_session_method_kill(message, session, error);
1096 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1097 Manager *m = userdata;
1105 r = sd_bus_message_read(message, "u", &uid);
1109 r = manager_get_user_from_creds(m, message, uid, error, &user);
1113 return bus_user_method_kill(message, user, error);
1116 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1117 Manager *m = userdata;
1125 r = sd_bus_message_read(message, "s", &name);
1129 r = manager_get_session_from_creds(m, message, name, error, &session);
1133 return bus_session_method_terminate(message, session, error);
1136 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1137 Manager *m = userdata;
1145 r = sd_bus_message_read(message, "u", &uid);
1149 r = manager_get_user_from_creds(m, message, uid, error, &user);
1153 return bus_user_method_terminate(message, user, error);
1156 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1157 Manager *m = userdata;
1165 r = sd_bus_message_read(message, "s", &name);
1169 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1173 return bus_seat_method_terminate(message, seat, error);
1176 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1177 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1178 _cleanup_free_ char *cc = NULL;
1179 Manager *m = userdata;
1180 int r, b, interactive;
1183 uint32_t uid, auth_uid;
1188 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1192 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
1193 SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1197 if (!uid_is_valid(uid)) {
1198 /* Note that we get the owner UID of the session or user unit,
1199 * not the actual client UID here! */
1200 r = sd_bus_creds_get_owner_uid(creds, &uid);
1205 /* owner_uid is racy, so for authorization we must use euid */
1206 r = sd_bus_creds_get_euid(creds, &auth_uid);
1213 return errno > 0 ? -errno : -ENOENT;
1215 r = bus_verify_polkit_async(
1218 uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
1219 "org.freedesktop.login1.set-user-linger",
1223 &m->polkit_registry,
1228 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1230 mkdir_p_label("/var/lib/elogind", 0755);
1232 r = mkdir_safe_label("/var/lib/elogind/linger", 0755, 0, 0, false);
1236 cc = cescape(pw->pw_name);
1240 path = strjoina("/var/lib/elogind/linger/", cc);
1248 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1255 if (r < 0 && errno != ENOENT)
1258 u = hashmap_get(m->users, UID_TO_PTR(uid));
1260 user_add_to_gc_queue(u);
1263 return sd_bus_reply_method_return(message, NULL);
1266 static int trigger_device(Manager *m, struct udev_device *d) {
1267 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1268 struct udev_list_entry *first, *item;
1273 e = udev_enumerate_new(m->udev);
1278 r = udev_enumerate_add_match_parent(e, d);
1283 r = udev_enumerate_scan_devices(e);
1287 first = udev_enumerate_get_list_entry(e);
1288 udev_list_entry_foreach(item, first) {
1289 _cleanup_free_ char *t = NULL;
1292 p = udev_list_entry_get_name(item);
1294 t = strappend(p, "/uevent");
1298 (void) write_string_file(t, "change", 0);
1304 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1305 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1306 _cleanup_free_ char *rule = NULL, *file = NULL;
1307 const char *id_for_seat;
1314 d = udev_device_new_from_syspath(m->udev, sysfs);
1318 if (!udev_device_has_tag(d, "seat"))
1321 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1325 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1328 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1331 mkdir_p_label("/etc/udev/rules.d", 0755);
1332 r = write_string_file_atomic_label(file, rule);
1336 return trigger_device(m, d);
1339 static int flush_devices(Manager *m) {
1340 _cleanup_closedir_ DIR *d;
1344 d = opendir("/etc/udev/rules.d");
1346 if (errno != ENOENT)
1347 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1351 FOREACH_DIRENT_ALL(de, d, break) {
1352 if (!dirent_is_file(de))
1355 if (!startswith(de->d_name, "72-seat-"))
1358 if (!endswith(de->d_name, ".rules"))
1361 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1362 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1366 return trigger_device(m, NULL);
1369 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1370 const char *sysfs, *seat;
1371 Manager *m = userdata;
1377 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1381 if (!path_startswith(sysfs, "/sys"))
1382 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1384 if (!seat_name_is_valid(seat))
1385 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1387 r = bus_verify_polkit_async(
1390 "org.freedesktop.login1.attach-device",
1394 &m->polkit_registry,
1399 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1401 r = attach_device(m, seat, sysfs);
1405 return sd_bus_reply_method_return(message, NULL);
1408 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1409 Manager *m = userdata;
1415 r = sd_bus_message_read(message, "b", &interactive);
1419 r = bus_verify_polkit_async(
1422 "org.freedesktop.login1.flush-devices",
1426 &m->polkit_registry,
1431 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1433 r = flush_devices(m);
1437 return sd_bus_reply_method_return(message, NULL);
1440 static int have_multiple_sessions(
1449 /* Check for other users' sessions. Greeter sessions do not
1450 * count, and non-login sessions do not count either. */
1451 HASHMAP_FOREACH(session, m->sessions, i)
1452 if (session->class == SESSION_USER &&
1453 session->user->uid != uid)
1459 #if 0 /// elogind has its own variant in elogind-dbus.c
1460 static int bus_manager_log_shutdown(
1462 const char *unit_name) {
1469 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1470 p = "MESSAGE=System is powering down";
1471 q = "SHUTDOWN=power-off";
1472 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1473 p = "MESSAGE=System is rebooting";
1474 q = "SHUTDOWN=reboot";
1475 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1476 p = "MESSAGE=System is halting";
1477 q = "SHUTDOWN=halt";
1478 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1479 p = "MESSAGE=System is rebooting with kexec";
1480 q = "SHUTDOWN=kexec";
1482 p = "MESSAGE=System is shutting down";
1486 if (isempty(m->wall_message))
1487 p = strjoina(p, ".");
1489 p = strjoina(p, " (", m->wall_message, ").");
1491 return log_struct(LOG_NOTICE,
1492 "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
1499 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1500 Manager *m = userdata;
1505 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1509 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1514 if (until <= now(CLOCK_MONOTONIC))
1517 /* We want to ignore the lid switch for a while after each
1518 * suspend, and after boot-up. Hence let's install a timer for
1519 * this. As long as the event source exists we ignore the lid
1522 if (m->lid_switch_ignore_event_source) {
1525 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1532 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1534 r = sd_event_add_time(
1536 &m->lid_switch_ignore_event_source,
1539 lid_switch_ignore_handler, m);
1544 #if 0 /// elogind-dbus.c needs to access this
1545 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1547 int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1550 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1551 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1552 [INHIBIT_SLEEP] = "PrepareForSleep"
1555 int active = _active;
1559 assert(w < _INHIBIT_WHAT_MAX);
1560 assert(signal_name[w]);
1562 return sd_bus_emit_signal(m->bus,
1563 "/org/freedesktop/login1",
1564 "org.freedesktop.login1.Manager",
1570 #if 0 /// elogind has its own variant in elogind-dbus.c
1571 static int execute_shutdown_or_sleep(
1574 const char *unit_name,
1575 sd_bus_error *error) {
1577 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1584 assert(w < _INHIBIT_WHAT_MAX);
1587 if (w == INHIBIT_SHUTDOWN)
1588 bus_manager_log_shutdown(m, unit_name);
1590 r = sd_bus_call_method(
1592 "org.freedesktop.systemd1",
1593 "/org/freedesktop/systemd1",
1594 "org.freedesktop.systemd1.Manager",
1598 "ss", unit_name, "replace-irreversibly");
1602 r = sd_bus_message_read(reply, "o", &p);
1612 m->action_unit = unit_name;
1613 free(m->action_job);
1617 /* Make sure the lid switch is ignored for a while */
1618 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1623 /* Tell people that they now may take a lock again */
1624 (void) send_prepare_for(m, w, false);
1629 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1631 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1632 Inhibitor *offending = NULL;
1637 if (manager->action_what == 0 || manager->action_job)
1640 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1641 _cleanup_free_ char *comm = NULL, *u = NULL;
1646 (void) get_process_comm(offending->pid, &comm);
1647 u = uid_to_name(offending->uid);
1649 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1650 offending->uid, strna(u),
1651 offending->pid, strna(comm));
1654 /* Actually do the operation */
1655 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1657 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1658 bus_error_message(&error, r));
1660 manager->action_unit = NULL;
1661 manager->action_what = 0;
1669 #if 0 /// elogind-dbus.c needs to access this
1670 static int manager_inhibit_timeout_handler(
1672 int manager_inhibit_timeout_handler(
1678 Manager *manager = userdata;
1682 assert(manager->inhibit_timeout_source == s);
1684 r = manager_dispatch_delayed(manager, true);
1685 return (r < 0) ? r : 0;
1688 #if 0 /// elogind has its own variant in elogind-dbus.c
1689 static int delay_shutdown_or_sleep(
1692 const char *unit_name) {
1699 assert(w < _INHIBIT_WHAT_MAX);
1702 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1704 if (m->inhibit_timeout_source) {
1705 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1707 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1709 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1711 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1713 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1714 timeout_val, 0, manager_inhibit_timeout_handler, m);
1719 m->action_unit = unit_name;
1726 #if 0 /// elogind has its own variant in elogind-dbus.c
1727 int bus_manager_shutdown_or_sleep_now_or_later(
1729 const char *unit_name,
1731 sd_bus_error *error) {
1739 assert(w <= _INHIBIT_WHAT_MAX);
1740 assert(!m->action_job);
1742 /* Tell everybody to prepare for shutdown/sleep */
1743 (void) send_prepare_for(m, w, true);
1746 m->inhibit_delay_max > 0 &&
1747 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1749 log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
1750 handle_action_to_string(action),
1751 delayed ? "" : "NOT ");
1753 /* Shutdown is delayed, keep in mind what we
1754 * want to do, and start a timeout */
1755 r = delay_shutdown_or_sleep(m, w, unit_name);
1757 /* Shutdown is not delayed, execute it
1759 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1765 #if 0 /// elogind-dbus.c needs to access this
1766 static int verify_shutdown_creds(
1768 int verify_shutdown_creds(
1771 sd_bus_message *message,
1775 const char *action_multiple_sessions,
1776 const char *action_ignore_inhibit,
1777 sd_bus_error *error) {
1779 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1780 bool multiple_sessions, blocked;
1787 assert(w <= _INHIBIT_WHAT_MAX);
1789 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1793 r = sd_bus_creds_get_euid(creds, &uid);
1797 r = have_multiple_sessions(m, uid);
1801 multiple_sessions = r > 0;
1802 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1804 if (multiple_sessions && action_multiple_sessions) {
1805 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1809 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1812 if (blocked && action_ignore_inhibit) {
1813 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1817 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1820 if (!multiple_sessions && !blocked && action) {
1821 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1825 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1831 #if 0 /// elogind has its own variant in elogind-dbus.c
1832 static int method_do_shutdown_or_sleep(
1834 sd_bus_message *message,
1835 const char *unit_name,
1838 const char *action_multiple_sessions,
1839 const char *action_ignore_inhibit,
1840 const char *sleep_verb,
1841 sd_bus_error *error) {
1849 assert(w <= _INHIBIT_WHAT_MAX);
1851 r = sd_bus_message_read(message, "b", &interactive);
1855 /* Don't allow multiple jobs being executed at the same time */
1857 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1860 r = can_sleep(sleep_verb);
1865 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1868 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1869 action_ignore_inhibit, error);
1870 log_debug_elogind("verify_shutdown_creds() returned %d", r);
1874 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1878 return sd_bus_reply_method_return(message, NULL);
1881 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1882 Manager *m = userdata;
1884 return method_do_shutdown_or_sleep(
1886 SPECIAL_POWEROFF_TARGET,
1888 "org.freedesktop.login1.power-off",
1889 "org.freedesktop.login1.power-off-multiple-sessions",
1890 "org.freedesktop.login1.power-off-ignore-inhibit",
1895 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1896 Manager *m = userdata;
1898 return method_do_shutdown_or_sleep(
1900 SPECIAL_REBOOT_TARGET,
1902 "org.freedesktop.login1.reboot",
1903 "org.freedesktop.login1.reboot-multiple-sessions",
1904 "org.freedesktop.login1.reboot-ignore-inhibit",
1909 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1910 Manager *m = userdata;
1912 return method_do_shutdown_or_sleep(
1914 SPECIAL_HALT_TARGET,
1916 "org.freedesktop.login1.halt",
1917 "org.freedesktop.login1.halt-multiple-sessions",
1918 "org.freedesktop.login1.halt-ignore-inhibit",
1923 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1924 Manager *m = userdata;
1926 return method_do_shutdown_or_sleep(
1928 SPECIAL_SUSPEND_TARGET,
1930 "org.freedesktop.login1.suspend",
1931 "org.freedesktop.login1.suspend-multiple-sessions",
1932 "org.freedesktop.login1.suspend-ignore-inhibit",
1937 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1938 Manager *m = userdata;
1940 return method_do_shutdown_or_sleep(
1942 SPECIAL_HIBERNATE_TARGET,
1944 "org.freedesktop.login1.hibernate",
1945 "org.freedesktop.login1.hibernate-multiple-sessions",
1946 "org.freedesktop.login1.hibernate-ignore-inhibit",
1951 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1952 Manager *m = userdata;
1954 return method_do_shutdown_or_sleep(
1956 SPECIAL_HYBRID_SLEEP_TARGET,
1958 "org.freedesktop.login1.hibernate",
1959 "org.freedesktop.login1.hibernate-multiple-sessions",
1960 "org.freedesktop.login1.hibernate-ignore-inhibit",
1966 static int nologin_timeout_handler(
1971 Manager *m = userdata;
1974 log_info("Creating /run/nologin, blocking further logins...");
1976 r = write_string_file_atomic_label("/run/nologin", "System is going down.");
1978 log_error_errno(r, "Failed to create /run/nologin: %m");
1980 m->unlink_nologin = true;
1985 static int update_schedule_file(Manager *m) {
1986 _cleanup_free_ char *temp_path = NULL;
1987 _cleanup_fclose_ FILE *f = NULL;
1992 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, false);
1994 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1996 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1998 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
2000 (void) fchmod(fileno(f), 0644);
2006 m->scheduled_shutdown_timeout,
2007 m->enable_wall_messages,
2008 m->scheduled_shutdown_type);
2010 if (!isempty(m->wall_message)) {
2011 _cleanup_free_ char *t;
2013 t = cescape(m->wall_message);
2019 fprintf(f, "WALL_MESSAGE=%s\n", t);
2022 r = fflush_and_check(f);
2026 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
2034 (void) unlink(temp_path);
2035 (void) unlink("/run/systemd/shutdown/scheduled");
2037 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
2040 static void reset_scheduled_shutdown(Manager *m) {
2043 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2044 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2045 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2047 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2048 m->scheduled_shutdown_timeout = 0;
2049 m->shutdown_dry_run = false;
2051 if (m->unlink_nologin) {
2052 (void) unlink("/run/nologin");
2053 m->unlink_nologin = false;
2056 (void) unlink("/run/systemd/shutdown/scheduled");
2059 #if 0 /// elogind has its own variant in elogind-dbus.c
2060 static int manager_scheduled_shutdown_handler(
2065 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2066 Manager *m = userdata;
2072 if (isempty(m->scheduled_shutdown_type))
2075 if (streq(m->scheduled_shutdown_type, "poweroff"))
2076 target = SPECIAL_POWEROFF_TARGET;
2077 else if (streq(m->scheduled_shutdown_type, "reboot"))
2078 target = SPECIAL_REBOOT_TARGET;
2079 else if (streq(m->scheduled_shutdown_type, "halt"))
2080 target = SPECIAL_HALT_TARGET;
2082 assert_not_reached("unexpected shutdown type");
2084 /* Don't allow multiple jobs being executed at the same time */
2085 if (m->action_what) {
2087 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
2091 if (m->shutdown_dry_run) {
2092 /* We do not process delay inhibitors here. Otherwise, we
2093 * would have to be considered "in progress" (like the check
2094 * above) for some seconds after our admin has seen the final
2097 bus_manager_log_shutdown(m, target);
2098 log_info("Running in dry run, suppressing action.");
2099 reset_scheduled_shutdown(m);
2104 r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
2106 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2113 reset_scheduled_shutdown(m);
2118 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2119 Manager *m = userdata;
2120 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2121 const char *action_multiple_sessions = NULL;
2122 const char *action_ignore_inhibit = NULL;
2123 const char *action = NULL;
2127 bool dry_run = false;
2132 log_debug_elogind("%s called", __FUNCTION__);
2133 r = sd_bus_message_read(message, "st", &type, &elapse);
2137 if (startswith(type, "dry-")) {
2142 if (streq(type, "poweroff")) {
2143 action = "org.freedesktop.login1.power-off";
2144 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2145 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2146 } else if (streq(type, "reboot")) {
2147 action = "org.freedesktop.login1.reboot";
2148 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2149 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2150 } else if (streq(type, "halt")) {
2151 action = "org.freedesktop.login1.halt";
2152 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2153 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
2155 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2157 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2158 action, action_multiple_sessions, action_ignore_inhibit, error);
2162 if (m->scheduled_shutdown_timeout_source) {
2163 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2165 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2167 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2169 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2171 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2172 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2174 return log_error_errno(r, "sd_event_add_time() failed: %m");
2177 r = free_and_strdup(&m->scheduled_shutdown_type, type);
2179 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2183 m->shutdown_dry_run = dry_run;
2185 if (m->nologin_timeout_source) {
2186 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2188 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2190 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2192 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2194 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2195 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2197 return log_error_errno(r, "sd_event_add_time() failed: %m");
2200 m->scheduled_shutdown_timeout = elapse;
2202 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2204 const char *tty = NULL;
2206 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2207 (void) sd_bus_creds_get_tty(creds, &tty);
2209 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2211 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2216 r = manager_setup_wall_message_timer(m);
2220 r = update_schedule_file(m);
2224 return sd_bus_reply_method_return(message, NULL);
2227 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2228 Manager *m = userdata;
2230 #if 1 /// elogind needs to construct the message to allow extra wall messages
2231 _cleanup_free_ char *l = NULL;
2237 log_debug_elogind("%s called", __FUNCTION__);
2238 cancelled = m->scheduled_shutdown_type != NULL;
2239 reset_scheduled_shutdown(m);
2242 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2243 const char *tty = NULL;
2247 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2249 (void) sd_bus_creds_get_uid(creds, &uid);
2250 (void) sd_bus_creds_get_tty(creds, &tty);
2253 #if 0 /// elogind wants to allow extra cancellation messages
2254 utmp_wall("The system shutdown has been cancelled",
2255 uid_to_name(uid), tty, logind_wall_tty_filter, m);
2257 r = asprintf(&l, "%s%sThe system shutdown has been cancelled!",
2258 strempty(m->wall_message),
2259 isempty(m->wall_message) ? "" : "\n");
2265 utmp_wall(l, uid_to_name(uid), tty, logind_wall_tty_filter, m);
2269 return sd_bus_reply_method_return(message, "b", cancelled);
2272 static int method_can_shutdown_or_sleep(
2274 sd_bus_message *message,
2277 const char *action_multiple_sessions,
2278 const char *action_ignore_inhibit,
2279 const char *sleep_verb,
2280 sd_bus_error *error) {
2282 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2283 bool multiple_sessions, challenge, blocked;
2284 const char *result = NULL;
2291 assert(w <= _INHIBIT_WHAT_MAX);
2293 assert(action_multiple_sessions);
2294 assert(action_ignore_inhibit);
2297 #if 0 /// elogind needs to have the manager being passed
2298 r = can_sleep(sleep_verb);
2300 r = can_sleep(m, sleep_verb);
2305 return sd_bus_reply_method_return(message, "s", "na");
2308 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2312 r = sd_bus_creds_get_euid(creds, &uid);
2316 r = have_multiple_sessions(m, uid);
2320 multiple_sessions = r > 0;
2321 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2323 if (multiple_sessions) {
2324 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2331 result = "challenge";
2337 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2341 if (r > 0 && !result)
2343 else if (challenge && (!result || streq(result, "yes")))
2344 result = "challenge";
2349 if (!multiple_sessions && !blocked) {
2350 /* If neither inhibit nor multiple sessions
2351 * apply then just check the normal policy */
2353 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2360 result = "challenge";
2365 return sd_bus_reply_method_return(message, "s", result);
2368 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2369 Manager *m = userdata;
2371 return method_can_shutdown_or_sleep(
2374 "org.freedesktop.login1.power-off",
2375 "org.freedesktop.login1.power-off-multiple-sessions",
2376 "org.freedesktop.login1.power-off-ignore-inhibit",
2381 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2382 Manager *m = userdata;
2384 return method_can_shutdown_or_sleep(
2387 "org.freedesktop.login1.reboot",
2388 "org.freedesktop.login1.reboot-multiple-sessions",
2389 "org.freedesktop.login1.reboot-ignore-inhibit",
2394 static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2395 Manager *m = userdata;
2397 return method_can_shutdown_or_sleep(
2400 "org.freedesktop.login1.halt",
2401 "org.freedesktop.login1.halt-multiple-sessions",
2402 "org.freedesktop.login1.halt-ignore-inhibit",
2407 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2408 Manager *m = userdata;
2410 return method_can_shutdown_or_sleep(
2413 "org.freedesktop.login1.suspend",
2414 "org.freedesktop.login1.suspend-multiple-sessions",
2415 "org.freedesktop.login1.suspend-ignore-inhibit",
2420 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2421 Manager *m = userdata;
2423 return method_can_shutdown_or_sleep(
2426 "org.freedesktop.login1.hibernate",
2427 "org.freedesktop.login1.hibernate-multiple-sessions",
2428 "org.freedesktop.login1.hibernate-ignore-inhibit",
2433 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2434 Manager *m = userdata;
2436 return method_can_shutdown_or_sleep(
2439 "org.freedesktop.login1.hibernate",
2440 "org.freedesktop.login1.hibernate-multiple-sessions",
2441 "org.freedesktop.login1.hibernate-ignore-inhibit",
2446 static int property_get_reboot_to_firmware_setup(
2449 const char *interface,
2450 const char *property,
2451 sd_bus_message *reply,
2453 sd_bus_error *error) {
2454 #if 0 /// elogind does not support EFI
2461 r = efi_get_reboot_to_firmware();
2462 if (r < 0 && r != -EOPNOTSUPP)
2463 log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
2465 return sd_bus_message_append(reply, "b", r > 0);
2467 return sd_bus_message_append(reply, "b", false);
2471 static int method_set_reboot_to_firmware_setup(
2472 sd_bus_message *message,
2474 sd_bus_error *error) {
2477 Manager *m = userdata;
2482 r = sd_bus_message_read(message, "b", &b);
2486 r = bus_verify_polkit_async(message,
2488 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2492 &m->polkit_registry,
2497 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2499 #if 0 /// elogind does not support EFI
2500 r = efi_set_reboot_to_firmware(b);
2505 return sd_bus_reply_method_return(message, NULL);
2508 static int method_can_reboot_to_firmware_setup(
2509 sd_bus_message *message,
2511 sd_bus_error *error) {
2513 #if 0 /// elogind does not support EFI
2517 Manager *m = userdata;
2522 r = efi_reboot_to_firmware_supported();
2524 if (r != -EOPNOTSUPP)
2525 log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m");
2527 return sd_bus_reply_method_return(message, "s", "na");
2530 r = bus_test_polkit(message,
2532 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2543 result = "challenge";
2547 return sd_bus_reply_method_return(message, "s", result);
2549 return sd_bus_reply_method_return(message, "s", "no");
2553 static int method_set_wall_message(
2554 sd_bus_message *message,
2556 sd_bus_error *error) {
2559 Manager *m = userdata;
2561 int enable_wall_messages;
2566 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2570 #if 0 /// elogind only calls this for shutdown/reboot, which already needs authorization.
2571 r = bus_verify_polkit_async(message,
2573 "org.freedesktop.login1.set-wall-message",
2577 &m->polkit_registry,
2582 return 1; /* Will call us back */
2585 r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
2589 m->enable_wall_messages = enable_wall_messages;
2591 return sd_bus_reply_method_return(message, NULL);
2594 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2595 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2596 const char *who, *why, *what, *mode;
2597 _cleanup_free_ char *id = NULL;
2598 _cleanup_close_ int fifo_fd = -1;
2599 Manager *m = userdata;
2600 Inhibitor *i = NULL;
2610 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2614 w = inhibit_what_from_string(what);
2616 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2618 mm = inhibit_mode_from_string(mode);
2620 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2622 /* Delay is only supported for shutdown/sleep */
2623 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2624 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2626 /* Don't allow taking delay locks while we are already
2627 * executing the operation. We shouldn't create the impression
2628 * that the lock was successful if the machine is about to go
2629 * down/suspend any moment. */
2630 if (m->action_what & w)
2631 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2633 r = bus_verify_polkit_async(
2636 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2637 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2638 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2639 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2640 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2641 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2642 "org.freedesktop.login1.inhibit-handle-lid-switch",
2646 &m->polkit_registry,
2651 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2653 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2657 r = sd_bus_creds_get_euid(creds, &uid);
2661 r = sd_bus_creds_get_pid(creds, &pid);
2665 if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
2666 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
2671 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2674 } while (hashmap_get(m->inhibitors, id));
2676 r = manager_add_inhibitor(m, id, &i);
2684 i->why = strdup(why);
2685 i->who = strdup(who);
2687 if (!i->why || !i->who) {
2692 fifo_fd = inhibitor_create_fifo(i);
2700 return sd_bus_reply_method_return(message, "h", fifo_fd);
2709 const sd_bus_vtable manager_vtable[] = {
2710 SD_BUS_VTABLE_START(0),
2712 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2713 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2715 #if 0 /// UNNEEDED by elogind
2716 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2718 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2719 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2720 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2721 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2722 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2723 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2724 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2725 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2726 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2727 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2728 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2729 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2730 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2731 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2732 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2733 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2734 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2735 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2736 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2737 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2738 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2739 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2740 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
2741 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
2742 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
2743 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
2744 SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
2745 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
2746 SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2748 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2749 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2750 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2751 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2752 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2753 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2754 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2755 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2756 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2757 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2758 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2759 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2760 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2761 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2762 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2763 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2764 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2765 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2766 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2767 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2768 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2769 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2770 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2771 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2772 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2773 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2774 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2775 SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2776 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2777 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2778 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2779 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2780 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2781 SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2782 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2783 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2784 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2785 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2786 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2787 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2788 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2789 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2790 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2792 SD_BUS_SIGNAL("SessionNew", "so", 0),
2793 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2794 SD_BUS_SIGNAL("UserNew", "uo", 0),
2795 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2796 SD_BUS_SIGNAL("SeatNew", "so", 0),
2797 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2798 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2799 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2804 #if 0 /// UNNEEDED by elogind
2805 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2814 if (streq(result, "done"))
2815 r = session_send_create_reply(s, NULL);
2817 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
2819 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2820 r = session_send_create_reply(s, &e);
2826 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2827 const char *path, *result, *unit;
2828 Manager *m = userdata;
2837 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2839 bus_log_parse_error(r);
2843 if (m->action_job && streq(m->action_job, path)) {
2844 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2846 /* Tell people that they now may take a lock again */
2847 (void) send_prepare_for(m, m->action_what, false);
2849 m->action_job = mfree(m->action_job);
2850 m->action_unit = NULL;
2855 session = hashmap_get(m->session_units, unit);
2856 if (session && streq_ptr(path, session->scope_job)) {
2857 session->scope_job = mfree(session->scope_job);
2858 session_jobs_reply(session, unit, result);
2860 session_save(session);
2861 user_save(session->user);
2862 session_add_to_gc_queue(session);
2865 user = hashmap_get(m->user_units, unit);
2867 (streq_ptr(path, user->service_job) ||
2868 streq_ptr(path, user->slice_job))) {
2870 if (streq_ptr(path, user->service_job))
2871 user->service_job = mfree(user->service_job);
2873 if (streq_ptr(path, user->slice_job))
2874 user->slice_job = mfree(user->slice_job);
2876 LIST_FOREACH(sessions_by_user, session, user->sessions)
2877 session_jobs_reply(session, unit, result);
2880 user_add_to_gc_queue(user);
2886 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2887 const char *path, *unit;
2888 Manager *m = userdata;
2896 r = sd_bus_message_read(message, "so", &unit, &path);
2898 bus_log_parse_error(r);
2902 session = hashmap_get(m->session_units, unit);
2904 session_add_to_gc_queue(session);
2906 user = hashmap_get(m->user_units, unit);
2908 user_add_to_gc_queue(user);
2913 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2914 _cleanup_free_ char *unit = NULL;
2915 Manager *m = userdata;
2924 path = sd_bus_message_get_path(message);
2928 r = unit_name_from_dbus_path(path, &unit);
2929 if (r == -EINVAL) /* not a unit */
2936 session = hashmap_get(m->session_units, unit);
2938 session_add_to_gc_queue(session);
2940 user = hashmap_get(m->user_units, unit);
2942 user_add_to_gc_queue(user);
2947 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2948 Manager *m = userdata;
2956 r = sd_bus_message_read(message, "b", &b);
2958 bus_log_parse_error(r);
2965 /* systemd finished reloading, let's recheck all our sessions */
2966 log_debug("System manager has been reloaded, rechecking sessions...");
2968 HASHMAP_FOREACH(session, m->sessions, i)
2969 session_add_to_gc_queue(session);
2975 int manager_send_changed(Manager *manager, const char *property, ...) {
2980 l = strv_from_stdarg_alloca(property);
2982 return sd_bus_emit_properties_changed_strv(
2984 "/org/freedesktop/login1",
2985 "org.freedesktop.login1.Manager",
2989 #if 0 /// UNNEEDED by elogind
2990 static int strdup_job(sd_bus_message *reply, char **job) {
2995 r = sd_bus_message_read(reply, "o", &j);
3007 int manager_start_slice(
3010 const char *description,
3014 sd_bus_error *error,
3017 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3024 r = sd_bus_message_new_method_call(
3027 "org.freedesktop.systemd1",
3028 "/org/freedesktop/systemd1",
3029 "org.freedesktop.systemd1.Manager",
3030 "StartTransientUnit");
3034 r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
3038 r = sd_bus_message_open_container(m, 'a', "(sv)");
3042 if (!isempty(description)) {
3043 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3048 if (!isempty(after)) {
3049 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3054 if (!isempty(after2)) {
3055 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3060 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3064 r = sd_bus_message_close_container(m);
3068 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3072 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3076 return strdup_job(reply, job);
3079 int manager_start_scope(
3084 const char *description,
3088 sd_bus_error *error,
3091 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3099 r = sd_bus_message_new_method_call(
3102 "org.freedesktop.systemd1",
3103 "/org/freedesktop/systemd1",
3104 "org.freedesktop.systemd1.Manager",
3105 "StartTransientUnit");
3109 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3113 r = sd_bus_message_open_container(m, 'a', "(sv)");
3117 if (!isempty(slice)) {
3118 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3123 if (!isempty(description)) {
3124 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3129 if (!isempty(after)) {
3130 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3135 if (!isempty(after2)) {
3136 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3141 /* cgroup empty notification is not available in containers
3142 * currently. To make this less problematic, let's shorten the
3143 * stop timeout for sessions, so that we don't wait
3146 /* Make sure that the session shells are terminated with
3147 * SIGHUP since bash and friends tend to ignore SIGTERM */
3148 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3152 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3156 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3160 r = sd_bus_message_close_container(m);
3164 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3168 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3172 return strdup_job(reply, job);
3175 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3176 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3183 r = sd_bus_call_method(
3185 "org.freedesktop.systemd1",
3186 "/org/freedesktop/systemd1",
3187 "org.freedesktop.systemd1.Manager",
3191 "ss", unit, "replace");
3195 return strdup_job(reply, job);
3198 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3199 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3206 r = sd_bus_call_method(
3208 "org.freedesktop.systemd1",
3209 "/org/freedesktop/systemd1",
3210 "org.freedesktop.systemd1.Manager",
3214 "ss", unit, "fail");
3216 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3217 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3220 sd_bus_error_free(error);
3227 return strdup_job(reply, job);
3230 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3231 _cleanup_free_ char *path = NULL;
3237 path = unit_dbus_path_from_name(scope);
3241 r = sd_bus_call_method(
3243 "org.freedesktop.systemd1",
3245 "org.freedesktop.systemd1.Scope",
3251 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3252 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3253 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3254 sd_bus_error_free(error);
3264 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3268 return sd_bus_call_method(
3270 "org.freedesktop.systemd1",
3271 "/org/freedesktop/systemd1",
3272 "org.freedesktop.systemd1.Manager",
3276 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3279 int manager_unit_is_active(Manager *manager, const char *unit) {
3280 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3281 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3282 _cleanup_free_ char *path = NULL;
3289 path = unit_dbus_path_from_name(unit);
3293 r = sd_bus_get_property(
3295 "org.freedesktop.systemd1",
3297 "org.freedesktop.systemd1.Unit",
3303 /* systemd might have droppped off momentarily, let's
3304 * not make this an error */
3305 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3306 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3309 /* If the unit is already unloaded then it's not
3311 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3312 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3318 r = sd_bus_message_read(reply, "s", &state);
3322 return !streq(state, "inactive") && !streq(state, "failed");
3325 int manager_job_is_active(Manager *manager, const char *path) {
3326 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3327 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3333 r = sd_bus_get_property(
3335 "org.freedesktop.systemd1",
3337 "org.freedesktop.systemd1.Job",
3343 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3344 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3347 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3353 /* We don't actually care about the state really. The fact
3354 * that we could read the job state is enough for us */