1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "sd-messages.h"
28 #include "alloc-util.h"
29 #include "audit-util.h"
30 #include "bus-common-errors.h"
31 #include "bus-error.h"
33 #include "dirent-util.h"
34 //#include "efivars.h"
37 #include "fileio-label.h"
38 #include "format-util.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 //#include "cgroup-util.h"
45 #include "selinux-util.h"
46 #include "sleep-config.h"
47 //#include "special.h"
49 #include "terminal-util.h"
50 #include "udev-util.h"
51 #include "unit-name.h"
52 #include "user-util.h"
53 #include "utmp-wtmp.h"
55 /// Additional includes needed by elogind
56 #include "elogind-dbus.h"
58 static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
60 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
65 /* Get client login session. This is not what you are looking for these days,
66 * as apps may instead belong to a user service unit. This includes terminal
67 * emulators and hence command-line apps. */
68 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
72 r = sd_bus_creds_get_session(creds, &name);
78 session = hashmap_get(m->sessions, name);
86 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
87 "Caller does not belong to any known session");
90 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
98 return get_sender_session(m, message, error, ret);
100 session = hashmap_get(m->sessions, name);
102 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
108 static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
110 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
115 /* Note that we get the owner UID of the session, not the actual client UID here! */
116 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
120 r = sd_bus_creds_get_owner_uid(creds, &uid);
126 user = hashmap_get(m->users, UID_TO_PTR(uid));
134 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "Caller does not belong to any logged in user or lingering user");
137 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
144 if (!uid_is_valid(uid))
145 return get_sender_user(m, message, error, ret);
147 user = hashmap_get(m->users, UID_TO_PTR(uid));
149 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "User ID "UID_FMT" is not logged in or lingering", uid);
155 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
166 r = manager_get_session_from_creds(m, message, NULL, error, &session);
170 seat = session->seat;
172 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
174 seat = hashmap_get(m->seats, name);
176 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
183 static int property_get_idle_hint(
186 const char *interface,
187 const char *property,
188 sd_bus_message *reply,
190 sd_bus_error *error) {
192 Manager *m = userdata;
198 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
201 static int property_get_idle_since_hint(
204 const char *interface,
205 const char *property,
206 sd_bus_message *reply,
208 sd_bus_error *error) {
210 Manager *m = userdata;
211 dual_timestamp t = DUAL_TIMESTAMP_NULL;
217 manager_get_idle_hint(m, &t);
219 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
222 static int property_get_inhibited(
225 const char *interface,
226 const char *property,
227 sd_bus_message *reply,
229 sd_bus_error *error) {
231 Manager *m = userdata;
238 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
240 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
243 static int property_get_preparing(
246 const char *interface,
247 const char *property,
248 sd_bus_message *reply,
250 sd_bus_error *error) {
252 Manager *m = userdata;
259 if (streq(property, "PreparingForShutdown"))
260 b = !!(m->action_what & INHIBIT_SHUTDOWN);
262 b = !!(m->action_what & INHIBIT_SLEEP);
264 return sd_bus_message_append(reply, "b", b);
267 static int property_get_scheduled_shutdown(
270 const char *interface,
271 const char *property,
272 sd_bus_message *reply,
274 sd_bus_error *error) {
276 Manager *m = userdata;
283 r = sd_bus_message_open_container(reply, 'r', "st");
287 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
291 return sd_bus_message_close_container(reply);
294 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
296 static int property_get_docked(
299 const char *interface,
300 const char *property,
301 sd_bus_message *reply,
303 sd_bus_error *error) {
305 Manager *m = userdata;
311 return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
314 static int property_get_current_sessions(
317 const char *interface,
318 const char *property,
319 sd_bus_message *reply,
321 sd_bus_error *error) {
323 Manager *m = userdata;
329 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
332 static int property_get_current_inhibitors(
335 const char *interface,
336 const char *property,
337 sd_bus_message *reply,
339 sd_bus_error *error) {
341 Manager *m = userdata;
347 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
350 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
351 _cleanup_free_ char *p = NULL;
352 Manager *m = userdata;
360 r = sd_bus_message_read(message, "s", &name);
364 r = manager_get_session_from_creds(m, message, name, error, &session);
368 p = session_bus_path(session);
372 return sd_bus_reply_method_return(message, "o", p);
375 /* Get login session of a process. This is not what you are looking for these days,
376 * as apps may instead belong to a user service unit. This includes terminal
377 * emulators and hence command-line apps. */
378 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
379 _cleanup_free_ char *p = NULL;
380 Session *session = NULL;
381 Manager *m = userdata;
388 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
390 r = sd_bus_message_read(message, "u", &pid);
397 r = manager_get_session_from_creds(m, message, NULL, error, &session);
401 r = manager_get_session_by_pid(m, pid, &session);
406 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
409 p = session_bus_path(session);
413 return sd_bus_reply_method_return(message, "o", p);
416 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
417 _cleanup_free_ char *p = NULL;
418 Manager *m = userdata;
426 r = sd_bus_message_read(message, "u", &uid);
430 r = manager_get_user_from_creds(m, message, uid, error, &user);
434 p = user_bus_path(user);
438 return sd_bus_reply_method_return(message, "o", p);
441 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
442 _cleanup_free_ char *p = NULL;
443 Manager *m = userdata;
451 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
453 r = sd_bus_message_read(message, "u", &pid);
460 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
464 r = manager_get_user_by_pid(m, pid, &user);
468 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
469 "PID "PID_FMT" does not belong to any logged in user or lingering user",
473 p = user_bus_path(user);
477 return sd_bus_reply_method_return(message, "o", p);
480 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
481 _cleanup_free_ char *p = NULL;
482 Manager *m = userdata;
490 r = sd_bus_message_read(message, "s", &name);
494 r = manager_get_seat_from_creds(m, message, name, error, &seat);
498 p = seat_bus_path(seat);
502 return sd_bus_reply_method_return(message, "o", p);
505 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
506 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
507 Manager *m = userdata;
515 r = sd_bus_message_new_method_return(message, &reply);
519 r = sd_bus_message_open_container(reply, 'a', "(susso)");
523 HASHMAP_FOREACH(session, m->sessions, i) {
524 _cleanup_free_ char *p = NULL;
526 p = session_bus_path(session);
530 r = sd_bus_message_append(reply, "(susso)",
532 (uint32_t) session->user->uid,
534 session->seat ? session->seat->id : "",
540 r = sd_bus_message_close_container(reply);
544 return sd_bus_send(NULL, reply, NULL);
547 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
548 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
549 Manager *m = userdata;
557 r = sd_bus_message_new_method_return(message, &reply);
561 r = sd_bus_message_open_container(reply, 'a', "(uso)");
565 HASHMAP_FOREACH(user, m->users, i) {
566 _cleanup_free_ char *p = NULL;
568 p = user_bus_path(user);
572 r = sd_bus_message_append(reply, "(uso)",
573 (uint32_t) user->uid,
580 r = sd_bus_message_close_container(reply);
584 return sd_bus_send(NULL, reply, NULL);
587 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
588 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
589 Manager *m = userdata;
597 r = sd_bus_message_new_method_return(message, &reply);
601 r = sd_bus_message_open_container(reply, 'a', "(so)");
605 HASHMAP_FOREACH(seat, m->seats, i) {
606 _cleanup_free_ char *p = NULL;
608 p = seat_bus_path(seat);
612 r = sd_bus_message_append(reply, "(so)", seat->id, p);
617 r = sd_bus_message_close_container(reply);
621 return sd_bus_send(NULL, reply, NULL);
624 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
625 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
626 Manager *m = userdata;
627 Inhibitor *inhibitor;
634 r = sd_bus_message_new_method_return(message, &reply);
638 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
642 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
644 r = sd_bus_message_append(reply, "(ssssuu)",
645 strempty(inhibit_what_to_string(inhibitor->what)),
646 strempty(inhibitor->who),
647 strempty(inhibitor->why),
648 strempty(inhibit_mode_to_string(inhibitor->mode)),
649 (uint32_t) inhibitor->uid,
650 (uint32_t) inhibitor->pid);
655 r = sd_bus_message_close_container(reply);
659 return sd_bus_send(NULL, reply, NULL);
662 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
663 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
664 uint32_t audit_id = 0;
665 _cleanup_free_ char *unit = NULL;
666 _cleanup_free_ char *id = NULL;
667 Session *session = NULL;
668 Manager *m = userdata;
682 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
683 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
685 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
689 if (!uid_is_valid(uid))
690 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
691 if (leader < 0 || leader == 1)
692 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
695 t = _SESSION_TYPE_INVALID;
697 t = session_type_from_string(type);
699 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
703 c = _SESSION_CLASS_INVALID;
705 c = session_class_from_string(class);
707 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
710 if (isempty(desktop))
713 if (!string_is_safe(desktop))
714 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
720 seat = hashmap_get(m->seats, cseat);
722 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
725 if (tty_is_vc(tty)) {
730 else if (seat != m->seat0)
731 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);
733 v = vtnr_from_tty(tty);
735 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
739 else if (vtnr != (uint32_t) v)
740 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
742 } else if (tty_is_console(tty)) {
746 else if (seat != m->seat0)
747 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
750 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
754 if (seat_has_vts(seat)) {
755 if (!vtnr || vtnr > 63)
756 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
759 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
763 r = sd_bus_message_enter_container(message, 'a', "(sv)");
767 if (t == _SESSION_TYPE_INVALID) {
768 if (!isempty(display))
770 else if (!isempty(tty))
773 t = SESSION_UNSPECIFIED;
776 if (c == _SESSION_CLASS_INVALID) {
777 if (t == SESSION_UNSPECIFIED)
778 c = SESSION_BACKGROUND;
784 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
786 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
790 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
796 * Check if we are already in a logind session. Or if we are in user@.service
797 * which is a special PAM session that avoids creating a logind session.
799 r = cg_pid_get_unit(leader, &unit);
802 if (hashmap_get(m->session_units, unit) ||
803 hashmap_get(m->user_units, unit))
804 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
807 * Old gdm and lightdm start the user-session on the same VT as
808 * the greeter session. But they destroy the greeter session
809 * after the user-session and want the user-session to take
810 * over the VT. We need to support this for
811 * backwards-compatibility, so make sure we allow new sessions
812 * on a VT that a greeter is running on. Furthermore, to allow
813 * re-logins, we have to allow a greeter to take over a used VT for
814 * the exact same reasons.
816 if (c != SESSION_GREETER &&
818 vtnr < m->seat0->position_count &&
819 m->seat0->positions[vtnr] &&
820 m->seat0->positions[vtnr]->class != SESSION_GREETER)
821 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
823 if (hashmap_size(m->sessions) >= m->sessions_max)
824 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
826 (void) audit_session_from_pid(leader, &audit_id);
827 if (audit_session_is_valid(audit_id)) {
828 /* Keep our session IDs and the audit session IDs in sync */
830 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
833 /* Wut? There's already a session by this name and we
834 * didn't find it above? Weird, then let's not trust
835 * the audit data and let's better register a new
837 if (hashmap_get(m->sessions, id)) {
838 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
839 audit_id = AUDIT_SESSION_INVALID;
849 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
852 } while (hashmap_get(m->sessions, id));
855 r = manager_add_user_by_uid(m, uid, &user);
859 r = manager_add_session(m, id, &session);
863 session_set_user(session, user);
865 session->leader = leader;
866 session->audit_id = audit_id;
869 session->remote = remote;
870 session->vtnr = vtnr;
873 session->tty = strdup(tty);
880 if (!isempty(display)) {
881 session->display = strdup(display);
882 if (!session->display) {
888 if (!isempty(remote_user)) {
889 session->remote_user = strdup(remote_user);
890 if (!session->remote_user) {
896 if (!isempty(remote_host)) {
897 session->remote_host = strdup(remote_host);
898 if (!session->remote_host) {
904 if (!isempty(service)) {
905 session->service = strdup(service);
906 if (!session->service) {
912 if (!isempty(desktop)) {
913 session->desktop = strdup(desktop);
914 if (!session->desktop) {
921 r = seat_attach_session(seat, session);
926 r = session_start(session);
930 session->create_message = sd_bus_message_ref(message);
932 #if 0 /// UNNEEDED by elogind
933 /* Now, let's wait until the slice unit and stuff got
934 * created. We send the reply back from
935 * session_send_create_reply(). */
937 /* We reply directly. */
939 r = session_send_create_reply(session, NULL);
948 session_add_to_gc_queue(session);
951 user_add_to_gc_queue(user);
956 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
957 Manager *m = userdata;
965 r = sd_bus_message_read(message, "s", &name);
969 r = manager_get_session_from_creds(m, message, name, error, &session);
973 r = session_release(session);
977 #if 1 /// elogind must queue this session
978 session_add_to_gc_queue(session);
980 return sd_bus_reply_method_return(message, NULL);
983 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
984 Manager *m = userdata;
992 r = sd_bus_message_read(message, "s", &name);
996 r = manager_get_session_from_creds(m, message, name, error, &session);
1000 return bus_session_method_activate(message, session, error);
1003 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1004 const char *session_name, *seat_name;
1005 Manager *m = userdata;
1013 /* Same as ActivateSession() but refuses to work if
1014 * the seat doesn't match */
1016 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
1020 r = manager_get_session_from_creds(m, message, session_name, error, &session);
1024 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
1028 if (session->seat != seat)
1029 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
1031 r = session_activate(session);
1035 return sd_bus_reply_method_return(message, NULL);
1038 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1039 Manager *m = userdata;
1047 r = sd_bus_message_read(message, "s", &name);
1051 r = manager_get_session_from_creds(m, message, name, error, &session);
1055 return bus_session_method_lock(message, session, error);
1058 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1059 Manager *m = userdata;
1065 r = bus_verify_polkit_async(
1068 "org.freedesktop.login1.lock-sessions",
1072 &m->polkit_registry,
1077 return 1; /* Will call us back */
1079 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1083 return sd_bus_reply_method_return(message, NULL);
1086 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1088 Manager *m = userdata;
1095 r = sd_bus_message_read(message, "s", &name);
1099 r = manager_get_session_from_creds(m, message, name, error, &session);
1103 return bus_session_method_kill(message, session, error);
1106 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1107 Manager *m = userdata;
1115 r = sd_bus_message_read(message, "u", &uid);
1119 r = manager_get_user_from_creds(m, message, uid, error, &user);
1123 return bus_user_method_kill(message, user, error);
1126 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1127 Manager *m = userdata;
1135 r = sd_bus_message_read(message, "s", &name);
1139 r = manager_get_session_from_creds(m, message, name, error, &session);
1143 return bus_session_method_terminate(message, session, error);
1146 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1147 Manager *m = userdata;
1155 r = sd_bus_message_read(message, "u", &uid);
1159 r = manager_get_user_from_creds(m, message, uid, error, &user);
1163 return bus_user_method_terminate(message, user, error);
1166 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1167 Manager *m = userdata;
1175 r = sd_bus_message_read(message, "s", &name);
1179 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1183 return bus_seat_method_terminate(message, seat, error);
1186 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1187 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1188 _cleanup_free_ char *cc = NULL;
1189 Manager *m = userdata;
1190 int r, b, interactive;
1193 uint32_t uid, auth_uid;
1198 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1202 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
1203 SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1207 if (!uid_is_valid(uid)) {
1208 /* Note that we get the owner UID of the session or user unit,
1209 * not the actual client UID here! */
1210 r = sd_bus_creds_get_owner_uid(creds, &uid);
1215 /* owner_uid is racy, so for authorization we must use euid */
1216 r = sd_bus_creds_get_euid(creds, &auth_uid);
1223 return errno > 0 ? -errno : -ENOENT;
1225 r = bus_verify_polkit_async(
1228 uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
1229 "org.freedesktop.login1.set-user-linger",
1233 &m->polkit_registry,
1238 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1240 mkdir_p_label("/var/lib/elogind", 0755);
1242 r = mkdir_safe_label("/var/lib/elogind/linger", 0755, 0, 0, 0);
1246 cc = cescape(pw->pw_name);
1250 path = strjoina("/var/lib/elogind/linger/", cc);
1258 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1265 if (r < 0 && errno != ENOENT)
1268 u = hashmap_get(m->users, UID_TO_PTR(uid));
1270 user_add_to_gc_queue(u);
1273 return sd_bus_reply_method_return(message, NULL);
1276 static int trigger_device(Manager *m, struct udev_device *d) {
1277 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1278 struct udev_list_entry *first, *item;
1283 e = udev_enumerate_new(m->udev);
1288 r = udev_enumerate_add_match_parent(e, d);
1293 r = udev_enumerate_scan_devices(e);
1297 first = udev_enumerate_get_list_entry(e);
1298 udev_list_entry_foreach(item, first) {
1299 _cleanup_free_ char *t = NULL;
1302 p = udev_list_entry_get_name(item);
1304 t = strappend(p, "/uevent");
1308 (void) write_string_file(t, "change", 0);
1314 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1315 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1316 _cleanup_free_ char *rule = NULL, *file = NULL;
1317 const char *id_for_seat;
1324 d = udev_device_new_from_syspath(m->udev, sysfs);
1328 if (!udev_device_has_tag(d, "seat"))
1331 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1335 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1338 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1341 mkdir_p_label("/etc/udev/rules.d", 0755);
1342 r = write_string_file_atomic_label(file, rule);
1346 return trigger_device(m, d);
1349 static int flush_devices(Manager *m) {
1350 _cleanup_closedir_ DIR *d;
1354 d = opendir("/etc/udev/rules.d");
1356 if (errno != ENOENT)
1357 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1361 FOREACH_DIRENT_ALL(de, d, break) {
1362 if (!dirent_is_file(de))
1365 if (!startswith(de->d_name, "72-seat-"))
1368 if (!endswith(de->d_name, ".rules"))
1371 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1372 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1376 return trigger_device(m, NULL);
1379 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1380 const char *sysfs, *seat;
1381 Manager *m = userdata;
1387 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1391 if (!path_startswith(sysfs, "/sys"))
1392 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1394 if (!seat_name_is_valid(seat))
1395 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1397 r = bus_verify_polkit_async(
1400 "org.freedesktop.login1.attach-device",
1404 &m->polkit_registry,
1409 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1411 r = attach_device(m, seat, sysfs);
1415 return sd_bus_reply_method_return(message, NULL);
1418 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1419 Manager *m = userdata;
1425 r = sd_bus_message_read(message, "b", &interactive);
1429 r = bus_verify_polkit_async(
1432 "org.freedesktop.login1.flush-devices",
1436 &m->polkit_registry,
1441 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1443 r = flush_devices(m);
1447 return sd_bus_reply_method_return(message, NULL);
1450 static int have_multiple_sessions(
1459 /* Check for other users' sessions. Greeter sessions do not
1460 * count, and non-login sessions do not count either. */
1461 HASHMAP_FOREACH(session, m->sessions, i)
1462 if (session->class == SESSION_USER &&
1463 session->user->uid != uid)
1469 #if 0 /// elogind has its own variant in elogind-dbus.c
1470 static int bus_manager_log_shutdown(
1472 const char *unit_name) {
1479 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1480 p = "MESSAGE=System is powering down";
1481 q = "SHUTDOWN=power-off";
1482 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1483 p = "MESSAGE=System is rebooting";
1484 q = "SHUTDOWN=reboot";
1485 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1486 p = "MESSAGE=System is halting";
1487 q = "SHUTDOWN=halt";
1488 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1489 p = "MESSAGE=System is rebooting with kexec";
1490 q = "SHUTDOWN=kexec";
1492 p = "MESSAGE=System is shutting down";
1496 if (isempty(m->wall_message))
1497 p = strjoina(p, ".");
1499 p = strjoina(p, " (", m->wall_message, ").");
1501 return log_struct(LOG_NOTICE,
1502 "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
1509 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1510 Manager *m = userdata;
1515 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1519 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1524 if (until <= now(CLOCK_MONOTONIC))
1527 /* We want to ignore the lid switch for a while after each
1528 * suspend, and after boot-up. Hence let's install a timer for
1529 * this. As long as the event source exists we ignore the lid
1532 if (m->lid_switch_ignore_event_source) {
1535 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1542 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1544 r = sd_event_add_time(
1546 &m->lid_switch_ignore_event_source,
1549 lid_switch_ignore_handler, m);
1554 #if 0 /// elogind-dbus.c needs to access this
1555 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1557 int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1560 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1561 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1562 [INHIBIT_SLEEP] = "PrepareForSleep"
1565 int active = _active;
1569 assert(w < _INHIBIT_WHAT_MAX);
1570 assert(signal_name[w]);
1572 return sd_bus_emit_signal(m->bus,
1573 "/org/freedesktop/login1",
1574 "org.freedesktop.login1.Manager",
1580 #if 0 /// elogind has its own variant in elogind-dbus.c
1581 static int execute_shutdown_or_sleep(
1584 const char *unit_name,
1585 sd_bus_error *error) {
1587 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1594 assert(w < _INHIBIT_WHAT_MAX);
1597 if (w == INHIBIT_SHUTDOWN)
1598 bus_manager_log_shutdown(m, unit_name);
1600 r = sd_bus_call_method(
1602 "org.freedesktop.systemd1",
1603 "/org/freedesktop/systemd1",
1604 "org.freedesktop.systemd1.Manager",
1608 "ss", unit_name, "replace-irreversibly");
1612 r = sd_bus_message_read(reply, "o", &p);
1622 m->action_unit = unit_name;
1623 free(m->action_job);
1627 /* Make sure the lid switch is ignored for a while */
1628 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1633 /* Tell people that they now may take a lock again */
1634 (void) send_prepare_for(m, w, false);
1640 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1642 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1643 Inhibitor *offending = NULL;
1648 #if 0 /// elogind has no action_job, but a pending_action
1649 if (manager->action_what == 0 || manager->action_job)
1651 if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
1655 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1656 _cleanup_free_ char *comm = NULL, *u = NULL;
1661 (void) get_process_comm(offending->pid, &comm);
1662 u = uid_to_name(offending->uid);
1664 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1665 offending->uid, strna(u),
1666 offending->pid, strna(comm));
1669 /* Actually do the operation */
1670 #if 0 /// elogind has no action_unit but a pending_action
1671 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1673 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
1676 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1677 bus_error_message(&error, r));
1680 #if 0 /// elogind has no action_unit but a pending_action
1681 manager->action_unit = NULL;
1682 manager->action_what = 0;
1685 manager->pending_action = HANDLE_IGNORE;
1686 manager->action_what = 0;
1687 /* It is not a critical error for elogind if suspending fails */
1694 static int manager_inhibit_timeout_handler(
1699 Manager *manager = userdata;
1703 assert(manager->inhibit_timeout_source == s);
1705 r = manager_dispatch_delayed(manager, true);
1706 return (r < 0) ? r : 0;
1709 #if 0 /// elogind does not have unit_name but action
1710 static int delay_shutdown_or_sleep(
1713 const char *unit_name) {
1716 int delay_shutdown_or_sleep(
1719 HandleAction action) {
1726 assert(w < _INHIBIT_WHAT_MAX);
1727 #if 0 /// UNNEEDED by elogind
1731 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1733 if (m->inhibit_timeout_source) {
1734 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1736 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1738 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1740 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1742 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1743 timeout_val, 0, manager_inhibit_timeout_handler, m);
1748 #if 0 /// elogind does not have unit_name but pendig_action
1749 m->action_unit = unit_name;
1751 m->pending_action = action;
1758 int bus_manager_shutdown_or_sleep_now_or_later(
1760 #if 0 /// elogind has HandleAction instead of const char* unit_name
1761 const char *unit_name,
1764 HandleAction unit_name,
1767 sd_bus_error *error) {
1772 #if 0 /// for elogind only w has to be checked.
1775 assert(w <= _INHIBIT_WHAT_MAX);
1776 assert(!m->action_job);
1779 assert(w <= _INHIBIT_WHAT_MAX);
1782 /* Tell everybody to prepare for shutdown/sleep */
1783 (void) send_prepare_for(m, w, true);
1786 m->inhibit_delay_max > 0 &&
1787 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1789 log_debug_elogind("%s called for %s (%sdelayed)", __FUNCTION__,
1790 handle_action_to_string(unit_name),
1791 delayed ? "" : "NOT ");
1793 /* Shutdown is delayed, keep in mind what we
1794 * want to do, and start a timeout */
1795 r = delay_shutdown_or_sleep(m, w, unit_name);
1797 /* Shutdown is not delayed, execute it
1799 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1804 static int verify_shutdown_creds(
1806 sd_bus_message *message,
1810 const char *action_multiple_sessions,
1811 const char *action_ignore_inhibit,
1812 sd_bus_error *error) {
1814 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1815 bool multiple_sessions, blocked;
1822 assert(w <= _INHIBIT_WHAT_MAX);
1824 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1828 r = sd_bus_creds_get_euid(creds, &uid);
1832 r = have_multiple_sessions(m, uid);
1836 multiple_sessions = r > 0;
1837 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1839 if (multiple_sessions && action_multiple_sessions) {
1840 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1844 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1847 if (blocked && action_ignore_inhibit) {
1848 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1852 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1855 if (!multiple_sessions && !blocked && action) {
1856 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1860 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1866 static int method_do_shutdown_or_sleep(
1868 sd_bus_message *message,
1869 #if 0 /// elogind has HandleAction instead of const char* unit_name
1870 const char *unit_name,
1872 HandleAction unit_name,
1876 const char *action_multiple_sessions,
1877 const char *action_ignore_inhibit,
1878 const char *sleep_verb,
1879 sd_bus_error *error) {
1885 #if 0 /// elogind does not need this to be checked
1889 assert(w <= _INHIBIT_WHAT_MAX);
1891 r = sd_bus_message_read(message, "b", &interactive);
1895 log_debug_elogind("%s called with action '%s', sleep '%s' (%sinteractive)",
1896 __FUNCTION__, action, sleep_verb,
1897 interactive ? "" : "NOT ");
1898 /* Don't allow multiple jobs being executed at the same time */
1900 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1903 #if 0 /// Within elogind the manager m must be provided, too
1904 r = can_sleep(sleep_verb);
1906 r = can_sleep(m, sleep_verb);
1912 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1915 #if 0 /// Within elogind it does not make sense to verify shutdown creds when suspending
1916 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1917 action_ignore_inhibit, error);
1921 if (IN_SET(unit_name, HANDLE_HALT, HANDLE_POWEROFF, HANDLE_REBOOT)) {
1922 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1923 action_ignore_inhibit, error);
1924 log_debug_elogind("verify_shutdown_creds() returned %d", r);
1930 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1934 return sd_bus_reply_method_return(message, NULL);
1937 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1938 Manager *m = userdata;
1940 log_debug_elogind("%s called", __FUNCTION__);
1941 return method_do_shutdown_or_sleep(
1943 #if 0 /// elogind uses HandleAction instead of const char* unti names
1944 SPECIAL_POWEROFF_TARGET,
1949 "org.freedesktop.login1.power-off",
1950 "org.freedesktop.login1.power-off-multiple-sessions",
1951 "org.freedesktop.login1.power-off-ignore-inhibit",
1956 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1957 Manager *m = userdata;
1959 log_debug_elogind("%s called", __FUNCTION__);
1960 return method_do_shutdown_or_sleep(
1962 #if 0 /// elogind uses HandleAction instead of const char* unti names
1963 SPECIAL_REBOOT_TARGET,
1968 "org.freedesktop.login1.reboot",
1969 "org.freedesktop.login1.reboot-multiple-sessions",
1970 "org.freedesktop.login1.reboot-ignore-inhibit",
1975 static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1976 Manager *m = userdata;
1978 log_debug_elogind("%s called", __FUNCTION__);
1979 return method_do_shutdown_or_sleep(
1981 #if 0 /// elogind uses HandleAction instead of const char* unti names
1982 SPECIAL_HALT_TARGET,
1987 "org.freedesktop.login1.halt",
1988 "org.freedesktop.login1.halt-multiple-sessions",
1989 "org.freedesktop.login1.halt-ignore-inhibit",
1994 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1995 Manager *m = userdata;
1997 log_debug_elogind("%s called", __FUNCTION__);
1998 return method_do_shutdown_or_sleep(
2000 #if 0 /// elogind uses HandleAction instead of const char* unti names
2001 SPECIAL_SUSPEND_TARGET,
2006 "org.freedesktop.login1.suspend",
2007 "org.freedesktop.login1.suspend-multiple-sessions",
2008 "org.freedesktop.login1.suspend-ignore-inhibit",
2013 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2014 Manager *m = userdata;
2016 log_debug_elogind("%s called", __FUNCTION__);
2017 return method_do_shutdown_or_sleep(
2019 #if 0 /// elogind uses HandleAction instead of const char* unti names
2020 SPECIAL_HIBERNATE_TARGET,
2025 "org.freedesktop.login1.hibernate",
2026 "org.freedesktop.login1.hibernate-multiple-sessions",
2027 "org.freedesktop.login1.hibernate-ignore-inhibit",
2032 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2033 Manager *m = userdata;
2035 log_debug_elogind("%s called", __FUNCTION__);
2036 return method_do_shutdown_or_sleep(
2038 #if 0 /// elogind uses HandleAction instead of const char* unti names
2039 SPECIAL_HYBRID_SLEEP_TARGET,
2041 "org.freedesktop.login1.hibernate",
2042 "org.freedesktop.login1.hibernate-multiple-sessions",
2043 "org.freedesktop.login1.hibernate-ignore-inhibit",
2048 static int method_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2049 Manager *m = userdata;
2051 return method_do_shutdown_or_sleep(
2053 SPECIAL_SUSPEND_TO_HIBERNATE_TARGET,
2055 HANDLE_HYBRID_SLEEP,
2058 "org.freedesktop.login1.hibernate",
2059 "org.freedesktop.login1.hibernate-multiple-sessions",
2060 "org.freedesktop.login1.hibernate-ignore-inhibit",
2065 static int nologin_timeout_handler(
2070 Manager *m = userdata;
2072 log_info("Creating /run/nologin, blocking further logins...");
2075 create_shutdown_run_nologin_or_warn() >= 0;
2080 static int update_schedule_file(Manager *m) {
2081 _cleanup_free_ char *temp_path = NULL;
2082 _cleanup_fclose_ FILE *f = NULL;
2087 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, 0);
2089 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
2091 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
2093 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
2095 (void) fchmod(fileno(f), 0644);
2101 m->scheduled_shutdown_timeout,
2102 m->enable_wall_messages,
2103 m->scheduled_shutdown_type);
2105 if (!isempty(m->wall_message)) {
2106 _cleanup_free_ char *t;
2108 t = cescape(m->wall_message);
2114 fprintf(f, "WALL_MESSAGE=%s\n", t);
2117 r = fflush_and_check(f);
2121 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
2129 (void) unlink(temp_path);
2130 (void) unlink("/run/systemd/shutdown/scheduled");
2132 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
2135 #if 0 /// elogind must access this from elogind-dbus.c
2136 static void reset_scheduled_shutdown(Manager *m) {
2138 void reset_scheduled_shutdown(Manager *m) {
2142 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2143 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2144 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
2146 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2147 m->scheduled_shutdown_timeout = 0;
2148 m->shutdown_dry_run = false;
2150 if (m->unlink_nologin) {
2151 (void) unlink_or_warn("/run/nologin");
2152 m->unlink_nologin = false;
2155 (void) unlink("/run/systemd/shutdown/scheduled");
2158 #if 0 /// elogind has its own variant in elogind-dbus.c
2159 static int manager_scheduled_shutdown_handler(
2164 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2165 Manager *m = userdata;
2171 if (isempty(m->scheduled_shutdown_type))
2174 if (streq(m->scheduled_shutdown_type, "poweroff"))
2175 target = SPECIAL_POWEROFF_TARGET;
2176 else if (streq(m->scheduled_shutdown_type, "reboot"))
2177 target = SPECIAL_REBOOT_TARGET;
2178 else if (streq(m->scheduled_shutdown_type, "halt"))
2179 target = SPECIAL_HALT_TARGET;
2181 assert_not_reached("unexpected shutdown type");
2183 /* Don't allow multiple jobs being executed at the same time */
2184 if (m->action_what) {
2186 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
2190 if (m->shutdown_dry_run) {
2191 /* We do not process delay inhibitors here. Otherwise, we
2192 * would have to be considered "in progress" (like the check
2193 * above) for some seconds after our admin has seen the final
2196 bus_manager_log_shutdown(m, target);
2197 log_info("Running in dry run, suppressing action.");
2198 reset_scheduled_shutdown(m);
2203 r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
2205 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2212 reset_scheduled_shutdown(m);
2217 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2218 Manager *m = userdata;
2219 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2220 const char *action_multiple_sessions = NULL;
2221 const char *action_ignore_inhibit = NULL;
2222 const char *action = NULL;
2226 bool dry_run = false;
2231 log_debug_elogind("%s called", __FUNCTION__);
2232 r = sd_bus_message_read(message, "st", &type, &elapse);
2236 if (startswith(type, "dry-")) {
2241 if (streq(type, "poweroff")) {
2242 action = "org.freedesktop.login1.power-off";
2243 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2244 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2245 } else if (streq(type, "reboot")) {
2246 action = "org.freedesktop.login1.reboot";
2247 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2248 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2249 } else if (streq(type, "halt")) {
2250 action = "org.freedesktop.login1.halt";
2251 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2252 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
2254 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2256 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2257 action, action_multiple_sessions, action_ignore_inhibit, error);
2261 if (m->scheduled_shutdown_timeout_source) {
2262 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2264 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2266 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2268 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2270 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2271 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2273 return log_error_errno(r, "sd_event_add_time() failed: %m");
2276 r = free_and_strdup(&m->scheduled_shutdown_type, type);
2278 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2282 m->shutdown_dry_run = dry_run;
2284 if (m->nologin_timeout_source) {
2285 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2287 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2289 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2291 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2293 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2294 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2296 return log_error_errno(r, "sd_event_add_time() failed: %m");
2299 m->scheduled_shutdown_timeout = elapse;
2301 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2303 const char *tty = NULL;
2305 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2306 (void) sd_bus_creds_get_tty(creds, &tty);
2308 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2310 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2315 r = manager_setup_wall_message_timer(m);
2319 r = update_schedule_file(m);
2323 return sd_bus_reply_method_return(message, NULL);
2326 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2327 Manager *m = userdata;
2329 #if 1 /// elogind needs to construct the message to allow extra wall messages
2330 _cleanup_free_ char *l = NULL;
2336 log_debug_elogind("%s called", __FUNCTION__);
2337 cancelled = m->scheduled_shutdown_type != NULL;
2338 reset_scheduled_shutdown(m);
2341 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2342 const char *tty = NULL;
2346 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2348 (void) sd_bus_creds_get_uid(creds, &uid);
2349 (void) sd_bus_creds_get_tty(creds, &tty);
2352 #if 0 /// elogind wants to allow extra cancellation messages
2353 utmp_wall("The system shutdown has been cancelled",
2354 uid_to_name(uid), tty, logind_wall_tty_filter, m);
2356 r = asprintf(&l, "%s%sThe system shutdown has been cancelled!",
2357 strempty(m->wall_message),
2358 isempty(m->wall_message) ? "" : "\n");
2364 utmp_wall(l, uid_to_name(uid), tty, logind_wall_tty_filter, m);
2368 return sd_bus_reply_method_return(message, "b", cancelled);
2371 static int method_can_shutdown_or_sleep(
2373 sd_bus_message *message,
2376 const char *action_multiple_sessions,
2377 const char *action_ignore_inhibit,
2378 const char *sleep_verb,
2379 sd_bus_error *error) {
2381 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2382 bool multiple_sessions, challenge, blocked;
2383 const char *result = NULL;
2390 assert(w <= _INHIBIT_WHAT_MAX);
2392 assert(action_multiple_sessions);
2393 assert(action_ignore_inhibit);
2396 #if 0 /// elogind needs to have the manager being passed
2397 r = can_sleep(sleep_verb);
2399 r = can_sleep(m, sleep_verb);
2404 return sd_bus_reply_method_return(message, "s", "na");
2407 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2411 r = sd_bus_creds_get_euid(creds, &uid);
2415 r = have_multiple_sessions(m, uid);
2419 multiple_sessions = r > 0;
2420 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2422 if (multiple_sessions) {
2423 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2430 result = "challenge";
2436 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2440 if (r > 0 && !result)
2442 else if (challenge && (!result || streq(result, "yes")))
2443 result = "challenge";
2448 if (!multiple_sessions && !blocked) {
2449 /* If neither inhibit nor multiple sessions
2450 * apply then just check the normal policy */
2452 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2459 result = "challenge";
2464 return sd_bus_reply_method_return(message, "s", result);
2467 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2468 Manager *m = userdata;
2470 return method_can_shutdown_or_sleep(
2473 "org.freedesktop.login1.power-off",
2474 "org.freedesktop.login1.power-off-multiple-sessions",
2475 "org.freedesktop.login1.power-off-ignore-inhibit",
2480 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2481 Manager *m = userdata;
2483 return method_can_shutdown_or_sleep(
2486 "org.freedesktop.login1.reboot",
2487 "org.freedesktop.login1.reboot-multiple-sessions",
2488 "org.freedesktop.login1.reboot-ignore-inhibit",
2493 static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2494 Manager *m = userdata;
2496 return method_can_shutdown_or_sleep(
2499 "org.freedesktop.login1.halt",
2500 "org.freedesktop.login1.halt-multiple-sessions",
2501 "org.freedesktop.login1.halt-ignore-inhibit",
2506 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2507 Manager *m = userdata;
2509 return method_can_shutdown_or_sleep(
2512 "org.freedesktop.login1.suspend",
2513 "org.freedesktop.login1.suspend-multiple-sessions",
2514 "org.freedesktop.login1.suspend-ignore-inhibit",
2519 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2520 Manager *m = userdata;
2522 return method_can_shutdown_or_sleep(
2525 "org.freedesktop.login1.hibernate",
2526 "org.freedesktop.login1.hibernate-multiple-sessions",
2527 "org.freedesktop.login1.hibernate-ignore-inhibit",
2532 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2533 Manager *m = userdata;
2535 return method_can_shutdown_or_sleep(
2538 "org.freedesktop.login1.hibernate",
2539 "org.freedesktop.login1.hibernate-multiple-sessions",
2540 "org.freedesktop.login1.hibernate-ignore-inhibit",
2545 static int method_can_suspend_to_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2546 Manager *m = userdata;
2548 return method_can_shutdown_or_sleep(
2551 "org.freedesktop.login1.hibernate",
2552 "org.freedesktop.login1.hibernate-multiple-sessions",
2553 "org.freedesktop.login1.hibernate-ignore-inhibit",
2554 "suspend-to-hibernate",
2558 static int property_get_reboot_to_firmware_setup(
2561 const char *interface,
2562 const char *property,
2563 sd_bus_message *reply,
2565 sd_bus_error *error) {
2566 #if 0 /// elogind does not support EFI
2573 r = efi_get_reboot_to_firmware();
2574 if (r < 0 && r != -EOPNOTSUPP)
2575 log_warning_errno(r, "Failed to determine reboot-to-firmware state: %m");
2577 return sd_bus_message_append(reply, "b", r > 0);
2579 return sd_bus_message_append(reply, "b", false);
2583 static int method_set_reboot_to_firmware_setup(
2584 sd_bus_message *message,
2586 sd_bus_error *error) {
2589 Manager *m = userdata;
2594 r = sd_bus_message_read(message, "b", &b);
2598 r = bus_verify_polkit_async(message,
2600 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2604 &m->polkit_registry,
2609 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2611 #if 0 /// elogind does not support EFI
2612 r = efi_set_reboot_to_firmware(b);
2617 return sd_bus_reply_method_return(message, NULL);
2620 static int method_can_reboot_to_firmware_setup(
2621 sd_bus_message *message,
2623 sd_bus_error *error) {
2625 #if 0 /// elogind does not support EFI
2629 Manager *m = userdata;
2634 r = efi_reboot_to_firmware_supported();
2636 if (r != -EOPNOTSUPP)
2637 log_warning_errno(errno, "Failed to determine whether reboot to firmware is supported: %m");
2639 return sd_bus_reply_method_return(message, "s", "na");
2642 r = bus_test_polkit(message,
2644 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2655 result = "challenge";
2659 return sd_bus_reply_method_return(message, "s", result);
2661 return sd_bus_reply_method_return(message, "s", "no");
2665 static int method_set_wall_message(
2666 sd_bus_message *message,
2668 sd_bus_error *error) {
2671 Manager *m = userdata;
2673 int enable_wall_messages;
2678 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2682 #if 0 /// elogind only calls this for shutdown/reboot, which already needs authorization.
2683 r = bus_verify_polkit_async(message,
2685 "org.freedesktop.login1.set-wall-message",
2689 &m->polkit_registry,
2694 return 1; /* Will call us back */
2697 r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
2701 m->enable_wall_messages = enable_wall_messages;
2703 return sd_bus_reply_method_return(message, NULL);
2706 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2707 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2708 const char *who, *why, *what, *mode;
2709 _cleanup_free_ char *id = NULL;
2710 _cleanup_close_ int fifo_fd = -1;
2711 Manager *m = userdata;
2712 Inhibitor *i = NULL;
2722 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2726 w = inhibit_what_from_string(what);
2728 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2730 mm = inhibit_mode_from_string(mode);
2732 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2734 /* Delay is only supported for shutdown/sleep */
2735 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2736 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2738 /* Don't allow taking delay locks while we are already
2739 * executing the operation. We shouldn't create the impression
2740 * that the lock was successful if the machine is about to go
2741 * down/suspend any moment. */
2742 if (m->action_what & w)
2743 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2745 r = bus_verify_polkit_async(
2748 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2749 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2750 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2751 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2752 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2753 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2754 "org.freedesktop.login1.inhibit-handle-lid-switch",
2758 &m->polkit_registry,
2763 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2765 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2769 r = sd_bus_creds_get_euid(creds, &uid);
2773 r = sd_bus_creds_get_pid(creds, &pid);
2777 if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
2778 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
2783 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2786 } while (hashmap_get(m->inhibitors, id));
2788 r = manager_add_inhibitor(m, id, &i);
2796 i->why = strdup(why);
2797 i->who = strdup(who);
2799 if (!i->why || !i->who) {
2804 fifo_fd = inhibitor_create_fifo(i);
2812 return sd_bus_reply_method_return(message, "h", fifo_fd);
2821 const sd_bus_vtable manager_vtable[] = {
2822 SD_BUS_VTABLE_START(0),
2824 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2825 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2827 #if 0 /// UNNEEDED by elogind
2828 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2830 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2831 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2832 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2833 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2834 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2835 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2836 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2837 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2838 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2839 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2840 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2841 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2842 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2843 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2844 SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
2845 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2846 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2847 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2848 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2849 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2850 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2851 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2852 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2853 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
2854 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
2855 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
2856 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
2857 SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
2858 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
2859 SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2861 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2862 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2863 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2864 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2865 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2866 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2867 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2868 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2869 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2870 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2871 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2872 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2873 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2874 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2875 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2876 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2877 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2878 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2879 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2880 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2881 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2882 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2883 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2884 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2885 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2886 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2887 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2888 SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2889 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2890 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2891 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2892 SD_BUS_METHOD("SuspendToHibernate", "b", NULL, method_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2893 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2894 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2895 SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
2896 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2897 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2898 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2899 SD_BUS_METHOD("CanSuspendToHibernate", NULL, "s", method_can_suspend_to_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2900 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2901 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2902 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2903 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2904 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2905 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2907 SD_BUS_SIGNAL("SessionNew", "so", 0),
2908 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2909 SD_BUS_SIGNAL("UserNew", "uo", 0),
2910 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2911 SD_BUS_SIGNAL("SeatNew", "so", 0),
2912 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2913 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2914 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2919 #if 0 /// UNNEEDED by elogind
2920 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2929 if (streq(result, "done"))
2930 r = session_send_create_reply(s, NULL);
2932 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
2934 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2935 r = session_send_create_reply(s, &e);
2941 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2942 const char *path, *result, *unit;
2943 Manager *m = userdata;
2952 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2954 bus_log_parse_error(r);
2958 if (m->action_job && streq(m->action_job, path)) {
2959 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2961 /* Tell people that they now may take a lock again */
2962 (void) send_prepare_for(m, m->action_what, false);
2964 m->action_job = mfree(m->action_job);
2965 m->action_unit = NULL;
2970 session = hashmap_get(m->session_units, unit);
2971 if (session && streq_ptr(path, session->scope_job)) {
2972 session->scope_job = mfree(session->scope_job);
2973 session_jobs_reply(session, unit, result);
2975 session_save(session);
2976 user_save(session->user);
2977 session_add_to_gc_queue(session);
2980 user = hashmap_get(m->user_units, unit);
2982 (streq_ptr(path, user->service_job) ||
2983 streq_ptr(path, user->slice_job))) {
2985 if (streq_ptr(path, user->service_job))
2986 user->service_job = mfree(user->service_job);
2988 if (streq_ptr(path, user->slice_job))
2989 user->slice_job = mfree(user->slice_job);
2991 LIST_FOREACH(sessions_by_user, session, user->sessions)
2992 session_jobs_reply(session, unit, result);
2995 user_add_to_gc_queue(user);
3001 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3002 const char *path, *unit;
3003 Manager *m = userdata;
3011 r = sd_bus_message_read(message, "so", &unit, &path);
3013 bus_log_parse_error(r);
3017 session = hashmap_get(m->session_units, unit);
3019 session_add_to_gc_queue(session);
3021 user = hashmap_get(m->user_units, unit);
3023 user_add_to_gc_queue(user);
3028 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3029 _cleanup_free_ char *unit = NULL;
3030 Manager *m = userdata;
3039 path = sd_bus_message_get_path(message);
3043 r = unit_name_from_dbus_path(path, &unit);
3044 if (r == -EINVAL) /* not a unit */
3051 session = hashmap_get(m->session_units, unit);
3053 session_add_to_gc_queue(session);
3055 user = hashmap_get(m->user_units, unit);
3057 user_add_to_gc_queue(user);
3062 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3063 Manager *m = userdata;
3071 r = sd_bus_message_read(message, "b", &b);
3073 bus_log_parse_error(r);
3080 /* systemd finished reloading, let's recheck all our sessions */
3081 log_debug("System manager has been reloaded, rechecking sessions...");
3083 HASHMAP_FOREACH(session, m->sessions, i)
3084 session_add_to_gc_queue(session);
3090 int manager_send_changed(Manager *manager, const char *property, ...) {
3095 l = strv_from_stdarg_alloca(property);
3097 return sd_bus_emit_properties_changed_strv(
3099 "/org/freedesktop/login1",
3100 "org.freedesktop.login1.Manager",
3104 #if 0 /// UNNEEDED by elogind
3105 static int strdup_job(sd_bus_message *reply, char **job) {
3110 r = sd_bus_message_read(reply, "o", &j);
3122 int manager_start_slice(
3125 const char *description,
3129 sd_bus_error *error,
3132 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3139 r = sd_bus_message_new_method_call(
3142 "org.freedesktop.systemd1",
3143 "/org/freedesktop/systemd1",
3144 "org.freedesktop.systemd1.Manager",
3145 "StartTransientUnit");
3149 r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
3153 r = sd_bus_message_open_container(m, 'a', "(sv)");
3157 if (!isempty(description)) {
3158 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3163 if (!isempty(after)) {
3164 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3169 if (!isempty(after2)) {
3170 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3175 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3179 r = sd_bus_message_close_container(m);
3183 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3187 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3191 return strdup_job(reply, job);
3194 int manager_start_scope(
3199 const char *description,
3203 sd_bus_error *error,
3206 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
3214 r = sd_bus_message_new_method_call(
3217 "org.freedesktop.systemd1",
3218 "/org/freedesktop/systemd1",
3219 "org.freedesktop.systemd1.Manager",
3220 "StartTransientUnit");
3224 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3228 r = sd_bus_message_open_container(m, 'a', "(sv)");
3232 if (!isempty(slice)) {
3233 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3238 if (!isempty(description)) {
3239 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3244 if (!isempty(after)) {
3245 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
3250 if (!isempty(after2)) {
3251 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
3256 /* cgroup empty notification is not available in containers
3257 * currently. To make this less problematic, let's shorten the
3258 * stop timeout for sessions, so that we don't wait
3261 /* Make sure that the session shells are terminated with
3262 * SIGHUP since bash and friends tend to ignore SIGTERM */
3263 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3267 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3271 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
3275 r = sd_bus_message_close_container(m);
3279 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3283 r = sd_bus_call(manager->bus, m, 0, error, &reply);
3287 return strdup_job(reply, job);
3290 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3291 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3298 r = sd_bus_call_method(
3300 "org.freedesktop.systemd1",
3301 "/org/freedesktop/systemd1",
3302 "org.freedesktop.systemd1.Manager",
3306 "ss", unit, "replace");
3310 return strdup_job(reply, job);
3313 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3314 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3321 r = sd_bus_call_method(
3323 "org.freedesktop.systemd1",
3324 "/org/freedesktop/systemd1",
3325 "org.freedesktop.systemd1.Manager",
3329 "ss", unit, "fail");
3331 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3332 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3335 sd_bus_error_free(error);
3342 return strdup_job(reply, job);
3345 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3346 _cleanup_free_ char *path = NULL;
3352 path = unit_dbus_path_from_name(scope);
3356 r = sd_bus_call_method(
3358 "org.freedesktop.systemd1",
3360 "org.freedesktop.systemd1.Scope",
3366 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3367 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3368 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3369 sd_bus_error_free(error);
3379 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3383 return sd_bus_call_method(
3385 "org.freedesktop.systemd1",
3386 "/org/freedesktop/systemd1",
3387 "org.freedesktop.systemd1.Manager",
3391 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3394 int manager_unit_is_active(Manager *manager, const char *unit) {
3395 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3396 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3397 _cleanup_free_ char *path = NULL;
3404 path = unit_dbus_path_from_name(unit);
3408 r = sd_bus_get_property(
3410 "org.freedesktop.systemd1",
3412 "org.freedesktop.systemd1.Unit",
3418 /* systemd might have droppped off momentarily, let's
3419 * not make this an error */
3420 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3421 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3424 /* If the unit is already unloaded then it's not
3426 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3427 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3433 r = sd_bus_message_read(reply, "s", &state);
3437 return !streq(state, "inactive") && !streq(state, "failed");
3440 int manager_job_is_active(Manager *manager, const char *path) {
3441 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3442 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3448 r = sd_bus_get_property(
3450 "org.freedesktop.systemd1",
3452 "org.freedesktop.systemd1.Job",
3458 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3459 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3462 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3468 /* We don't actually care about the state really. The fact
3469 * that we could read the job state is enough for us */