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"
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"
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 static int get_sender_session(Manager
*m
, sd_bus_message
*message
, sd_bus_error
*error
, Session
**ret
) {
56 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
61 /* Get client login session. This is not what you are looking for these days,
62 * as apps may instead belong to a user service unit. This includes terminal
63 * emulators and hence command-line apps. */
64 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_AUGMENT
, &creds
);
68 r
= sd_bus_creds_get_session(creds
, &name
);
74 session
= hashmap_get(m
->sessions
, name
);
82 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
,
83 "Caller does not belong to any known session");
86 int manager_get_session_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Session
**ret
) {
94 return get_sender_session(m
, message
, error
, ret
);
96 session
= hashmap_get(m
->sessions
, name
);
98 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SESSION
, "No session '%s' known", name
);
104 static int get_sender_user(Manager
*m
, sd_bus_message
*message
, sd_bus_error
*error
, User
**ret
) {
106 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
111 /* Note that we get the owner UID of the session, not the actual client UID here! */
112 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
116 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
122 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
130 return sd_bus_error_setf(error
, BUS_ERROR_NO_USER_FOR_PID
, "Caller does not belong to any logged in user or lingering user");
133 int manager_get_user_from_creds(Manager
*m
, sd_bus_message
*message
, uid_t uid
, sd_bus_error
*error
, User
**ret
) {
140 if (!uid_is_valid(uid
))
141 return get_sender_user(m
, message
, error
, ret
);
143 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
145 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER
, "User ID "UID_FMT
" is not logged in or lingering", uid
);
151 int manager_get_seat_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Seat
**ret
) {
162 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
166 seat
= session
->seat
;
168 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "Session has no seat.");
170 seat
= hashmap_get(m
->seats
, name
);
172 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", name
);
179 static int property_get_idle_hint(
182 const char *interface
,
183 const char *property
,
184 sd_bus_message
*reply
,
186 sd_bus_error
*error
) {
188 Manager
*m
= userdata
;
194 return sd_bus_message_append(reply
, "b", manager_get_idle_hint(m
, NULL
) > 0);
197 static int property_get_idle_since_hint(
200 const char *interface
,
201 const char *property
,
202 sd_bus_message
*reply
,
204 sd_bus_error
*error
) {
206 Manager
*m
= userdata
;
207 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
213 manager_get_idle_hint(m
, &t
);
215 return sd_bus_message_append(reply
, "t", streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
);
218 static int property_get_inhibited(
221 const char *interface
,
222 const char *property
,
223 sd_bus_message
*reply
,
225 sd_bus_error
*error
) {
227 Manager
*m
= userdata
;
234 w
= manager_inhibit_what(m
, streq(property
, "BlockInhibited") ? INHIBIT_BLOCK
: INHIBIT_DELAY
);
236 return sd_bus_message_append(reply
, "s", inhibit_what_to_string(w
));
239 static int property_get_preparing(
242 const char *interface
,
243 const char *property
,
244 sd_bus_message
*reply
,
246 sd_bus_error
*error
) {
248 Manager
*m
= userdata
;
255 if (streq(property
, "PreparingForShutdown"))
256 b
= !!(m
->action_what
& INHIBIT_SHUTDOWN
);
258 b
= !!(m
->action_what
& INHIBIT_SLEEP
);
260 return sd_bus_message_append(reply
, "b", b
);
263 static int property_get_scheduled_shutdown(
266 const char *interface
,
267 const char *property
,
268 sd_bus_message
*reply
,
270 sd_bus_error
*error
) {
272 Manager
*m
= userdata
;
279 r
= sd_bus_message_open_container(reply
, 'r', "st");
283 r
= sd_bus_message_append(reply
, "st", m
->scheduled_shutdown_type
, m
->scheduled_shutdown_timeout
);
287 return sd_bus_message_close_container(reply
);
290 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action
, handle_action
, HandleAction
);
292 static int property_get_docked(
295 const char *interface
,
296 const char *property
,
297 sd_bus_message
*reply
,
299 sd_bus_error
*error
) {
301 Manager
*m
= userdata
;
307 return sd_bus_message_append(reply
, "b", manager_is_docked_or_external_displays(m
));
310 static int property_get_current_sessions(
313 const char *interface
,
314 const char *property
,
315 sd_bus_message
*reply
,
317 sd_bus_error
*error
) {
319 Manager
*m
= userdata
;
325 return sd_bus_message_append(reply
, "t", (uint64_t) hashmap_size(m
->sessions
));
328 static int property_get_current_inhibitors(
331 const char *interface
,
332 const char *property
,
333 sd_bus_message
*reply
,
335 sd_bus_error
*error
) {
337 Manager
*m
= userdata
;
343 return sd_bus_message_append(reply
, "t", (uint64_t) hashmap_size(m
->inhibitors
));
346 static int method_get_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
347 _cleanup_free_
char *p
= NULL
;
348 Manager
*m
= userdata
;
356 r
= sd_bus_message_read(message
, "s", &name
);
360 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
364 p
= session_bus_path(session
);
368 return sd_bus_reply_method_return(message
, "o", p
);
371 /* Get login session of a process. This is not what you are looking for these days,
372 * as apps may instead belong to a user service unit. This includes terminal
373 * emulators and hence command-line apps. */
374 static int method_get_session_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
375 _cleanup_free_
char *p
= NULL
;
376 Session
*session
= NULL
;
377 Manager
*m
= userdata
;
384 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
386 r
= sd_bus_message_read(message
, "u", &pid
);
393 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
397 r
= manager_get_session_by_pid(m
, pid
, &session
);
402 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
405 p
= session_bus_path(session
);
409 return sd_bus_reply_method_return(message
, "o", p
);
412 static int method_get_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
413 _cleanup_free_
char *p
= NULL
;
414 Manager
*m
= userdata
;
422 r
= sd_bus_message_read(message
, "u", &uid
);
426 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
430 p
= user_bus_path(user
);
434 return sd_bus_reply_method_return(message
, "o", p
);
437 static int method_get_user_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
438 _cleanup_free_
char *p
= NULL
;
439 Manager
*m
= userdata
;
447 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
449 r
= sd_bus_message_read(message
, "u", &pid
);
456 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
460 r
= manager_get_user_by_pid(m
, pid
, &user
);
464 return sd_bus_error_setf(error
, BUS_ERROR_NO_USER_FOR_PID
,
465 "PID "PID_FMT
" does not belong to any logged in user or lingering user",
469 p
= user_bus_path(user
);
473 return sd_bus_reply_method_return(message
, "o", p
);
476 static int method_get_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
477 _cleanup_free_
char *p
= NULL
;
478 Manager
*m
= userdata
;
486 r
= sd_bus_message_read(message
, "s", &name
);
490 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
494 p
= seat_bus_path(seat
);
498 return sd_bus_reply_method_return(message
, "o", p
);
501 static int method_list_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
502 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
503 Manager
*m
= userdata
;
511 r
= sd_bus_message_new_method_return(message
, &reply
);
515 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
519 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
520 _cleanup_free_
char *p
= NULL
;
522 p
= session_bus_path(session
);
526 r
= sd_bus_message_append(reply
, "(susso)",
528 (uint32_t) session
->user
->uid
,
530 session
->seat
? session
->seat
->id
: "",
536 r
= sd_bus_message_close_container(reply
);
540 return sd_bus_send(NULL
, reply
, NULL
);
543 static int method_list_users(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
544 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
545 Manager
*m
= userdata
;
553 r
= sd_bus_message_new_method_return(message
, &reply
);
557 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
561 HASHMAP_FOREACH(user
, m
->users
, i
) {
562 _cleanup_free_
char *p
= NULL
;
564 p
= user_bus_path(user
);
568 r
= sd_bus_message_append(reply
, "(uso)",
569 (uint32_t) user
->uid
,
576 r
= sd_bus_message_close_container(reply
);
580 return sd_bus_send(NULL
, reply
, NULL
);
583 static int method_list_seats(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
584 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
585 Manager
*m
= userdata
;
593 r
= sd_bus_message_new_method_return(message
, &reply
);
597 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
601 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
602 _cleanup_free_
char *p
= NULL
;
604 p
= seat_bus_path(seat
);
608 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
613 r
= sd_bus_message_close_container(reply
);
617 return sd_bus_send(NULL
, reply
, NULL
);
620 static int method_list_inhibitors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
621 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
622 Manager
*m
= userdata
;
623 Inhibitor
*inhibitor
;
630 r
= sd_bus_message_new_method_return(message
, &reply
);
634 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
638 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
640 r
= sd_bus_message_append(reply
, "(ssssuu)",
641 strempty(inhibit_what_to_string(inhibitor
->what
)),
642 strempty(inhibitor
->who
),
643 strempty(inhibitor
->why
),
644 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
645 (uint32_t) inhibitor
->uid
,
646 (uint32_t) inhibitor
->pid
);
651 r
= sd_bus_message_close_container(reply
);
655 return sd_bus_send(NULL
, reply
, NULL
);
658 static int method_create_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
659 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
660 uint32_t audit_id
= 0;
661 _cleanup_free_
char *id
= NULL
;
662 Session
*session
= NULL
;
663 Manager
*m
= userdata
;
677 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
678 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
680 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
684 if (!uid_is_valid(uid
))
685 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid UID");
686 if (leader
< 0 || leader
== 1)
687 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
690 t
= _SESSION_TYPE_INVALID
;
692 t
= session_type_from_string(type
);
694 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
698 c
= _SESSION_CLASS_INVALID
;
700 c
= session_class_from_string(class);
702 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
705 if (isempty(desktop
))
708 if (!string_is_safe(desktop
))
709 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
715 seat
= hashmap_get(m
->seats
, cseat
);
717 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
720 if (tty_is_vc(tty
)) {
725 else if (seat
!= m
->seat0
)
726 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
);
728 v
= vtnr_from_tty(tty
);
730 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
734 else if (vtnr
!= (uint32_t) v
)
735 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
737 } else if (tty_is_console(tty
)) {
741 else if (seat
!= m
->seat0
)
742 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
745 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
749 if (seat_has_vts(seat
)) {
750 if (!vtnr
|| vtnr
> 63)
751 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
754 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
758 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
762 if (t
== _SESSION_TYPE_INVALID
) {
763 if (!isempty(display
))
765 else if (!isempty(tty
))
768 t
= SESSION_UNSPECIFIED
;
771 if (c
== _SESSION_CLASS_INVALID
) {
772 if (t
== SESSION_UNSPECIFIED
)
773 c
= SESSION_BACKGROUND
;
779 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
781 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
785 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
790 r
= manager_get_session_by_pid(m
, leader
, NULL
);
792 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already running in a session");
795 * Old gdm and lightdm start the user-session on the same VT as
796 * the greeter session. But they destroy the greeter session
797 * after the user-session and want the user-session to take
798 * over the VT. We need to support this for
799 * backwards-compatibility, so make sure we allow new sessions
800 * on a VT that a greeter is running on. Furthermore, to allow
801 * re-logins, we have to allow a greeter to take over a used VT for
802 * the exact same reasons.
804 if (c
!= SESSION_GREETER
&&
806 vtnr
< m
->seat0
->position_count
&&
807 m
->seat0
->positions
[vtnr
] &&
808 m
->seat0
->positions
[vtnr
]->class != SESSION_GREETER
)
809 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already occupied by a session");
811 if (hashmap_size(m
->sessions
) >= m
->sessions_max
)
812 return sd_bus_error_setf(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Maximum number of sessions (%" PRIu64
") reached, refusing further sessions.", m
->sessions_max
);
814 (void) audit_session_from_pid(leader
, &audit_id
);
815 if (audit_session_is_valid(audit_id
)) {
816 /* Keep our session IDs and the audit session IDs in sync */
818 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
821 /* Wut? There's already a session by this name and we
822 * didn't find it above? Weird, then let's not trust
823 * the audit data and let's better register a new
825 if (hashmap_get(m
->sessions
, id
)) {
826 log_warning("Existing logind session ID %s used by new audit session, ignoring", id
);
827 audit_id
= AUDIT_SESSION_INVALID
;
837 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
840 } while (hashmap_get(m
->sessions
, id
));
843 r
= manager_add_user_by_uid(m
, uid
, &user
);
847 r
= manager_add_session(m
, id
, &session
);
851 session_set_user(session
, user
);
853 session
->leader
= leader
;
854 session
->audit_id
= audit_id
;
857 session
->remote
= remote
;
858 session
->vtnr
= vtnr
;
861 session
->tty
= strdup(tty
);
868 if (!isempty(display
)) {
869 session
->display
= strdup(display
);
870 if (!session
->display
) {
876 if (!isempty(remote_user
)) {
877 session
->remote_user
= strdup(remote_user
);
878 if (!session
->remote_user
) {
884 if (!isempty(remote_host
)) {
885 session
->remote_host
= strdup(remote_host
);
886 if (!session
->remote_host
) {
892 if (!isempty(service
)) {
893 session
->service
= strdup(service
);
894 if (!session
->service
) {
900 if (!isempty(desktop
)) {
901 session
->desktop
= strdup(desktop
);
902 if (!session
->desktop
) {
909 r
= seat_attach_session(seat
, session
);
914 r
= session_start(session
);
918 session
->create_message
= sd_bus_message_ref(message
);
920 /* Now, let's wait until the slice unit and stuff got
921 * created. We send the reply back from
922 * session_send_create_reply(). */
928 session_add_to_gc_queue(session
);
931 user_add_to_gc_queue(user
);
936 static int method_release_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
937 Manager
*m
= userdata
;
945 r
= sd_bus_message_read(message
, "s", &name
);
949 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
953 r
= session_release(session
);
957 return sd_bus_reply_method_return(message
, NULL
);
960 static int method_activate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
961 Manager
*m
= userdata
;
969 r
= sd_bus_message_read(message
, "s", &name
);
973 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
977 return bus_session_method_activate(message
, session
, error
);
980 static int method_activate_session_on_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
981 const char *session_name
, *seat_name
;
982 Manager
*m
= userdata
;
990 /* Same as ActivateSession() but refuses to work if
991 * the seat doesn't match */
993 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
997 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
1001 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
1005 if (session
->seat
!= seat
)
1006 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
1008 r
= session_activate(session
);
1012 return sd_bus_reply_method_return(message
, NULL
);
1015 static int method_lock_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1016 Manager
*m
= userdata
;
1024 r
= sd_bus_message_read(message
, "s", &name
);
1028 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1032 return bus_session_method_lock(message
, session
, error
);
1035 static int method_lock_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1036 Manager
*m
= userdata
;
1042 r
= bus_verify_polkit_async(
1045 "org.freedesktop.login1.lock-sessions",
1049 &m
->polkit_registry
,
1054 return 1; /* Will call us back */
1056 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
1060 return sd_bus_reply_method_return(message
, NULL
);
1063 static int method_kill_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1065 Manager
*m
= userdata
;
1072 r
= sd_bus_message_read(message
, "s", &name
);
1076 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1080 return bus_session_method_kill(message
, session
, error
);
1083 static int method_kill_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1084 Manager
*m
= userdata
;
1092 r
= sd_bus_message_read(message
, "u", &uid
);
1096 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1100 return bus_user_method_kill(message
, user
, error
);
1103 static int method_terminate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1104 Manager
*m
= userdata
;
1112 r
= sd_bus_message_read(message
, "s", &name
);
1116 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1120 return bus_session_method_terminate(message
, session
, error
);
1123 static int method_terminate_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1124 Manager
*m
= userdata
;
1132 r
= sd_bus_message_read(message
, "u", &uid
);
1136 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1140 return bus_user_method_terminate(message
, user
, error
);
1143 static int method_terminate_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1144 Manager
*m
= userdata
;
1152 r
= sd_bus_message_read(message
, "s", &name
);
1156 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
1160 return bus_seat_method_terminate(message
, seat
, error
);
1163 static int method_set_user_linger(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1164 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1165 _cleanup_free_
char *cc
= NULL
;
1166 Manager
*m
= userdata
;
1167 int r
, b
, interactive
;
1170 uint32_t uid
, auth_uid
;
1175 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1179 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|
1180 SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1184 if (!uid_is_valid(uid
)) {
1185 /* Note that we get the owner UID of the session or user unit,
1186 * not the actual client UID here! */
1187 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1192 /* owner_uid is racy, so for authorization we must use euid */
1193 r
= sd_bus_creds_get_euid(creds
, &auth_uid
);
1200 return errno
> 0 ? -errno
: -ENOENT
;
1202 r
= bus_verify_polkit_async(
1205 uid
== auth_uid
? "org.freedesktop.login1.set-self-linger" :
1206 "org.freedesktop.login1.set-user-linger",
1210 &m
->polkit_registry
,
1215 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1217 mkdir_p_label("/var/lib/systemd", 0755);
1219 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, false);
1223 cc
= cescape(pw
->pw_name
);
1227 path
= strjoina("/var/lib/systemd/linger/", cc
);
1235 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1242 if (r
< 0 && errno
!= ENOENT
)
1245 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1247 user_add_to_gc_queue(u
);
1250 return sd_bus_reply_method_return(message
, NULL
);
1253 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1254 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1255 struct udev_list_entry
*first
, *item
;
1260 e
= udev_enumerate_new(m
->udev
);
1265 r
= udev_enumerate_add_match_parent(e
, d
);
1270 r
= udev_enumerate_scan_devices(e
);
1274 first
= udev_enumerate_get_list_entry(e
);
1275 udev_list_entry_foreach(item
, first
) {
1276 _cleanup_free_
char *t
= NULL
;
1279 p
= udev_list_entry_get_name(item
);
1281 t
= strappend(p
, "/uevent");
1285 (void) write_string_file(t
, "change", 0);
1291 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1292 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1293 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1294 const char *id_for_seat
;
1301 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1305 if (!udev_device_has_tag(d
, "seat"))
1308 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1312 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1315 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1318 mkdir_p_label("/etc/udev/rules.d", 0755);
1319 r
= write_string_file_atomic_label(file
, rule
);
1323 return trigger_device(m
, d
);
1326 static int flush_devices(Manager
*m
) {
1327 _cleanup_closedir_
DIR *d
;
1331 d
= opendir("/etc/udev/rules.d");
1333 if (errno
!= ENOENT
)
1334 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1338 FOREACH_DIRENT_ALL(de
, d
, break) {
1339 if (!dirent_is_file(de
))
1342 if (!startswith(de
->d_name
, "72-seat-"))
1345 if (!endswith(de
->d_name
, ".rules"))
1348 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1349 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1353 return trigger_device(m
, NULL
);
1356 static int method_attach_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1357 const char *sysfs
, *seat
;
1358 Manager
*m
= userdata
;
1364 r
= sd_bus_message_read(message
, "ssb", &seat
, &sysfs
, &interactive
);
1368 if (!path_startswith(sysfs
, "/sys"))
1369 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not in /sys", sysfs
);
1371 if (!seat_name_is_valid(seat
))
1372 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat %s is not valid", seat
);
1374 r
= bus_verify_polkit_async(
1377 "org.freedesktop.login1.attach-device",
1381 &m
->polkit_registry
,
1386 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1388 r
= attach_device(m
, seat
, sysfs
);
1392 return sd_bus_reply_method_return(message
, NULL
);
1395 static int method_flush_devices(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1396 Manager
*m
= userdata
;
1402 r
= sd_bus_message_read(message
, "b", &interactive
);
1406 r
= bus_verify_polkit_async(
1409 "org.freedesktop.login1.flush-devices",
1413 &m
->polkit_registry
,
1418 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1420 r
= flush_devices(m
);
1424 return sd_bus_reply_method_return(message
, NULL
);
1427 static int have_multiple_sessions(
1436 /* Check for other users' sessions. Greeter sessions do not
1437 * count, and non-login sessions do not count either. */
1438 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1439 if (session
->class == SESSION_USER
&&
1440 session
->user
->uid
!= uid
)
1446 static int bus_manager_log_shutdown(
1448 const char *unit_name
) {
1455 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1456 p
= "MESSAGE=System is powering down";
1457 q
= "SHUTDOWN=power-off";
1458 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1459 p
= "MESSAGE=System is rebooting";
1460 q
= "SHUTDOWN=reboot";
1461 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1462 p
= "MESSAGE=System is halting";
1463 q
= "SHUTDOWN=halt";
1464 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1465 p
= "MESSAGE=System is rebooting with kexec";
1466 q
= "SHUTDOWN=kexec";
1468 p
= "MESSAGE=System is shutting down";
1472 if (isempty(m
->wall_message
))
1473 p
= strjoina(p
, ".");
1475 p
= strjoina(p
, " (", m
->wall_message
, ").");
1477 return log_struct(LOG_NOTICE
,
1478 "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR
,
1484 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1485 Manager
*m
= userdata
;
1490 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1494 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1499 if (until
<= now(CLOCK_MONOTONIC
))
1502 /* We want to ignore the lid switch for a while after each
1503 * suspend, and after boot-up. Hence let's install a timer for
1504 * this. As long as the event source exists we ignore the lid
1507 if (m
->lid_switch_ignore_event_source
) {
1510 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1517 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1519 r
= sd_event_add_time(
1521 &m
->lid_switch_ignore_event_source
,
1524 lid_switch_ignore_handler
, m
);
1529 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1531 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1532 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1533 [INHIBIT_SLEEP
] = "PrepareForSleep"
1536 int active
= _active
;
1540 assert(w
< _INHIBIT_WHAT_MAX
);
1541 assert(signal_name
[w
]);
1543 return sd_bus_emit_signal(m
->bus
,
1544 "/org/freedesktop/login1",
1545 "org.freedesktop.login1.Manager",
1551 static int execute_shutdown_or_sleep(
1554 const char *unit_name
,
1555 sd_bus_error
*error
) {
1557 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1564 assert(w
< _INHIBIT_WHAT_MAX
);
1567 if (w
== INHIBIT_SHUTDOWN
)
1568 bus_manager_log_shutdown(m
, unit_name
);
1570 r
= sd_bus_call_method(
1572 "org.freedesktop.systemd1",
1573 "/org/freedesktop/systemd1",
1574 "org.freedesktop.systemd1.Manager",
1578 "ss", unit_name
, "replace-irreversibly");
1582 r
= sd_bus_message_read(reply
, "o", &p
);
1592 m
->action_unit
= unit_name
;
1593 free(m
->action_job
);
1597 /* Make sure the lid switch is ignored for a while */
1598 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1603 /* Tell people that they now may take a lock again */
1604 (void) send_prepare_for(m
, w
, false);
1609 int manager_dispatch_delayed(Manager
*manager
, bool timeout
) {
1611 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1612 Inhibitor
*offending
= NULL
;
1617 if (manager
->action_what
== 0 || manager
->action_job
)
1620 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1621 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1626 (void) get_process_comm(offending
->pid
, &comm
);
1627 u
= uid_to_name(offending
->uid
);
1629 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1630 offending
->uid
, strna(u
),
1631 offending
->pid
, strna(comm
));
1634 /* Actually do the operation */
1635 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1637 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1638 bus_error_message(&error
, r
));
1640 manager
->action_unit
= NULL
;
1641 manager
->action_what
= 0;
1648 static int manager_inhibit_timeout_handler(
1653 Manager
*manager
= userdata
;
1657 assert(manager
->inhibit_timeout_source
== s
);
1659 r
= manager_dispatch_delayed(manager
, true);
1660 return (r
< 0) ? r
: 0;
1663 static int delay_shutdown_or_sleep(
1666 const char *unit_name
) {
1673 assert(w
< _INHIBIT_WHAT_MAX
);
1676 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1678 if (m
->inhibit_timeout_source
) {
1679 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1681 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1683 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1685 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1687 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1688 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1693 m
->action_unit
= unit_name
;
1699 int bus_manager_shutdown_or_sleep_now_or_later(
1701 const char *unit_name
,
1703 sd_bus_error
*error
) {
1711 assert(w
<= _INHIBIT_WHAT_MAX
);
1712 assert(!m
->action_job
);
1714 /* Tell everybody to prepare for shutdown/sleep */
1715 (void) send_prepare_for(m
, w
, true);
1718 m
->inhibit_delay_max
> 0 &&
1719 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1722 /* Shutdown is delayed, keep in mind what we
1723 * want to do, and start a timeout */
1724 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1726 /* Shutdown is not delayed, execute it
1728 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1733 static int verify_shutdown_creds(
1735 sd_bus_message
*message
,
1739 const char *action_multiple_sessions
,
1740 const char *action_ignore_inhibit
,
1741 sd_bus_error
*error
) {
1743 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1744 bool multiple_sessions
, blocked
;
1751 assert(w
<= _INHIBIT_WHAT_MAX
);
1753 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1757 r
= sd_bus_creds_get_euid(creds
, &uid
);
1761 r
= have_multiple_sessions(m
, uid
);
1765 multiple_sessions
= r
> 0;
1766 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1768 if (multiple_sessions
&& action_multiple_sessions
) {
1769 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1773 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1776 if (blocked
&& action_ignore_inhibit
) {
1777 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1781 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1784 if (!multiple_sessions
&& !blocked
&& action
) {
1785 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1789 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1795 static int method_do_shutdown_or_sleep(
1797 sd_bus_message
*message
,
1798 const char *unit_name
,
1801 const char *action_multiple_sessions
,
1802 const char *action_ignore_inhibit
,
1803 const char *sleep_verb
,
1804 sd_bus_error
*error
) {
1812 assert(w
<= _INHIBIT_WHAT_MAX
);
1814 r
= sd_bus_message_read(message
, "b", &interactive
);
1818 /* Don't allow multiple jobs being executed at the same time */
1820 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1823 r
= can_sleep(sleep_verb
);
1828 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1831 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1832 action_ignore_inhibit
, error
);
1836 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1840 return sd_bus_reply_method_return(message
, NULL
);
1843 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1844 Manager
*m
= userdata
;
1846 return method_do_shutdown_or_sleep(
1848 SPECIAL_POWEROFF_TARGET
,
1850 "org.freedesktop.login1.power-off",
1851 "org.freedesktop.login1.power-off-multiple-sessions",
1852 "org.freedesktop.login1.power-off-ignore-inhibit",
1857 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1858 Manager
*m
= userdata
;
1860 return method_do_shutdown_or_sleep(
1862 SPECIAL_REBOOT_TARGET
,
1864 "org.freedesktop.login1.reboot",
1865 "org.freedesktop.login1.reboot-multiple-sessions",
1866 "org.freedesktop.login1.reboot-ignore-inhibit",
1871 static int method_halt(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1872 Manager
*m
= userdata
;
1874 return method_do_shutdown_or_sleep(
1876 SPECIAL_HALT_TARGET
,
1878 "org.freedesktop.login1.halt",
1879 "org.freedesktop.login1.halt-multiple-sessions",
1880 "org.freedesktop.login1.halt-ignore-inhibit",
1885 static int method_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1886 Manager
*m
= userdata
;
1888 return method_do_shutdown_or_sleep(
1890 SPECIAL_SUSPEND_TARGET
,
1892 "org.freedesktop.login1.suspend",
1893 "org.freedesktop.login1.suspend-multiple-sessions",
1894 "org.freedesktop.login1.suspend-ignore-inhibit",
1899 static int method_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1900 Manager
*m
= userdata
;
1902 return method_do_shutdown_or_sleep(
1904 SPECIAL_HIBERNATE_TARGET
,
1906 "org.freedesktop.login1.hibernate",
1907 "org.freedesktop.login1.hibernate-multiple-sessions",
1908 "org.freedesktop.login1.hibernate-ignore-inhibit",
1913 static int method_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1914 Manager
*m
= userdata
;
1916 return method_do_shutdown_or_sleep(
1918 SPECIAL_HYBRID_SLEEP_TARGET
,
1920 "org.freedesktop.login1.hibernate",
1921 "org.freedesktop.login1.hibernate-multiple-sessions",
1922 "org.freedesktop.login1.hibernate-ignore-inhibit",
1927 static int nologin_timeout_handler(
1932 Manager
*m
= userdata
;
1934 log_info("Creating /run/nologin, blocking further logins...");
1937 create_shutdown_run_nologin_or_warn() >= 0;
1942 static int update_schedule_file(Manager
*m
) {
1943 _cleanup_free_
char *temp_path
= NULL
;
1944 _cleanup_fclose_
FILE *f
= NULL
;
1949 r
= mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, false);
1951 return log_error_errno(r
, "Failed to create shutdown subdirectory: %m");
1953 r
= fopen_temporary("/run/systemd/shutdown/scheduled", &f
, &temp_path
);
1955 return log_error_errno(r
, "Failed to save information about scheduled shutdowns: %m");
1957 (void) fchmod(fileno(f
), 0644);
1963 m
->scheduled_shutdown_timeout
,
1964 m
->enable_wall_messages
,
1965 m
->scheduled_shutdown_type
);
1967 if (!isempty(m
->wall_message
)) {
1968 _cleanup_free_
char *t
;
1970 t
= cescape(m
->wall_message
);
1976 fprintf(f
, "WALL_MESSAGE=%s\n", t
);
1979 r
= fflush_and_check(f
);
1983 if (rename(temp_path
, "/run/systemd/shutdown/scheduled") < 0) {
1991 (void) unlink(temp_path
);
1992 (void) unlink("/run/systemd/shutdown/scheduled");
1994 return log_error_errno(r
, "Failed to write information about scheduled shutdowns: %m");
1997 static void reset_scheduled_shutdown(Manager
*m
) {
2000 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2001 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
2002 m
->nologin_timeout_source
= sd_event_source_unref(m
->nologin_timeout_source
);
2004 m
->scheduled_shutdown_type
= mfree(m
->scheduled_shutdown_type
);
2005 m
->scheduled_shutdown_timeout
= 0;
2006 m
->shutdown_dry_run
= false;
2008 if (m
->unlink_nologin
) {
2009 (void) unlink_or_warn("/run/nologin");
2010 m
->unlink_nologin
= false;
2013 (void) unlink("/run/systemd/shutdown/scheduled");
2016 static int manager_scheduled_shutdown_handler(
2021 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2022 Manager
*m
= userdata
;
2028 if (isempty(m
->scheduled_shutdown_type
))
2031 if (streq(m
->scheduled_shutdown_type
, "poweroff"))
2032 target
= SPECIAL_POWEROFF_TARGET
;
2033 else if (streq(m
->scheduled_shutdown_type
, "reboot"))
2034 target
= SPECIAL_REBOOT_TARGET
;
2035 else if (streq(m
->scheduled_shutdown_type
, "halt"))
2036 target
= SPECIAL_HALT_TARGET
;
2038 assert_not_reached("unexpected shutdown type");
2040 /* Don't allow multiple jobs being executed at the same time */
2041 if (m
->action_what
) {
2043 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target
);
2047 if (m
->shutdown_dry_run
) {
2048 /* We do not process delay inhibitors here. Otherwise, we
2049 * would have to be considered "in progress" (like the check
2050 * above) for some seconds after our admin has seen the final
2053 bus_manager_log_shutdown(m
, target
);
2054 log_info("Running in dry run, suppressing action.");
2055 reset_scheduled_shutdown(m
);
2060 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, target
, INHIBIT_SHUTDOWN
, &error
);
2062 log_error_errno(r
, "Scheduled shutdown to %s failed: %m", target
);
2069 reset_scheduled_shutdown(m
);
2073 static int method_schedule_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2074 Manager
*m
= userdata
;
2075 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2076 const char *action_multiple_sessions
= NULL
;
2077 const char *action_ignore_inhibit
= NULL
;
2078 const char *action
= NULL
;
2082 bool dry_run
= false;
2087 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
2091 if (startswith(type
, "dry-")) {
2096 if (streq(type
, "poweroff")) {
2097 action
= "org.freedesktop.login1.power-off";
2098 action_multiple_sessions
= "org.freedesktop.login1.power-off-multiple-sessions";
2099 action_ignore_inhibit
= "org.freedesktop.login1.power-off-ignore-inhibit";
2100 } else if (streq(type
, "reboot")) {
2101 action
= "org.freedesktop.login1.reboot";
2102 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
2103 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
2104 } else if (streq(type
, "halt")) {
2105 action
= "org.freedesktop.login1.halt";
2106 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
2107 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
2109 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
2111 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
2112 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
2116 if (m
->scheduled_shutdown_timeout_source
) {
2117 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
2119 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
2121 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
2123 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
2125 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
2126 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
2128 return log_error_errno(r
, "sd_event_add_time() failed: %m");
2131 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
2133 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2137 m
->shutdown_dry_run
= dry_run
;
2139 if (m
->nologin_timeout_source
) {
2140 r
= sd_event_source_set_time(m
->nologin_timeout_source
, elapse
);
2142 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
2144 r
= sd_event_source_set_enabled(m
->nologin_timeout_source
, SD_EVENT_ONESHOT
);
2146 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
2148 r
= sd_event_add_time(m
->event
, &m
->nologin_timeout_source
,
2149 CLOCK_REALTIME
, elapse
- 5 * USEC_PER_MINUTE
, 0, nologin_timeout_handler
, m
);
2151 return log_error_errno(r
, "sd_event_add_time() failed: %m");
2154 m
->scheduled_shutdown_timeout
= elapse
;
2156 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2158 const char *tty
= NULL
;
2160 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
2161 (void) sd_bus_creds_get_tty(creds
, &tty
);
2163 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
2165 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2170 r
= manager_setup_wall_message_timer(m
);
2174 r
= update_schedule_file(m
);
2178 return sd_bus_reply_method_return(message
, NULL
);
2181 static int method_cancel_scheduled_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2182 Manager
*m
= userdata
;
2188 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
2189 reset_scheduled_shutdown(m
);
2192 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2193 const char *tty
= NULL
;
2197 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2199 (void) sd_bus_creds_get_uid(creds
, &uid
);
2200 (void) sd_bus_creds_get_tty(creds
, &tty
);
2203 utmp_wall("The system shutdown has been cancelled",
2204 uid_to_name(uid
), tty
, logind_wall_tty_filter
, m
);
2207 return sd_bus_reply_method_return(message
, "b", cancelled
);
2210 static int method_can_shutdown_or_sleep(
2212 sd_bus_message
*message
,
2215 const char *action_multiple_sessions
,
2216 const char *action_ignore_inhibit
,
2217 const char *sleep_verb
,
2218 sd_bus_error
*error
) {
2220 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2221 bool multiple_sessions
, challenge
, blocked
;
2222 const char *result
= NULL
;
2229 assert(w
<= _INHIBIT_WHAT_MAX
);
2231 assert(action_multiple_sessions
);
2232 assert(action_ignore_inhibit
);
2235 r
= can_sleep(sleep_verb
);
2239 return sd_bus_reply_method_return(message
, "s", "na");
2242 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
2246 r
= sd_bus_creds_get_euid(creds
, &uid
);
2250 r
= have_multiple_sessions(m
, uid
);
2254 multiple_sessions
= r
> 0;
2255 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
2257 if (multiple_sessions
) {
2258 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, UID_INVALID
, &challenge
, error
);
2265 result
= "challenge";
2271 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, UID_INVALID
, &challenge
, error
);
2275 if (r
> 0 && !result
)
2277 else if (challenge
&& (!result
|| streq(result
, "yes")))
2278 result
= "challenge";
2283 if (!multiple_sessions
&& !blocked
) {
2284 /* If neither inhibit nor multiple sessions
2285 * apply then just check the normal policy */
2287 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, NULL
, UID_INVALID
, &challenge
, error
);
2294 result
= "challenge";
2299 return sd_bus_reply_method_return(message
, "s", result
);
2302 static int method_can_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2303 Manager
*m
= userdata
;
2305 return method_can_shutdown_or_sleep(
2308 "org.freedesktop.login1.power-off",
2309 "org.freedesktop.login1.power-off-multiple-sessions",
2310 "org.freedesktop.login1.power-off-ignore-inhibit",
2315 static int method_can_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2316 Manager
*m
= userdata
;
2318 return method_can_shutdown_or_sleep(
2321 "org.freedesktop.login1.reboot",
2322 "org.freedesktop.login1.reboot-multiple-sessions",
2323 "org.freedesktop.login1.reboot-ignore-inhibit",
2328 static int method_can_halt(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2329 Manager
*m
= userdata
;
2331 return method_can_shutdown_or_sleep(
2334 "org.freedesktop.login1.halt",
2335 "org.freedesktop.login1.halt-multiple-sessions",
2336 "org.freedesktop.login1.halt-ignore-inhibit",
2341 static int method_can_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2342 Manager
*m
= userdata
;
2344 return method_can_shutdown_or_sleep(
2347 "org.freedesktop.login1.suspend",
2348 "org.freedesktop.login1.suspend-multiple-sessions",
2349 "org.freedesktop.login1.suspend-ignore-inhibit",
2354 static int method_can_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2355 Manager
*m
= userdata
;
2357 return method_can_shutdown_or_sleep(
2360 "org.freedesktop.login1.hibernate",
2361 "org.freedesktop.login1.hibernate-multiple-sessions",
2362 "org.freedesktop.login1.hibernate-ignore-inhibit",
2367 static int method_can_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2368 Manager
*m
= userdata
;
2370 return method_can_shutdown_or_sleep(
2373 "org.freedesktop.login1.hibernate",
2374 "org.freedesktop.login1.hibernate-multiple-sessions",
2375 "org.freedesktop.login1.hibernate-ignore-inhibit",
2380 static int property_get_reboot_to_firmware_setup(
2383 const char *interface
,
2384 const char *property
,
2385 sd_bus_message
*reply
,
2387 sd_bus_error
*error
) {
2394 r
= efi_get_reboot_to_firmware();
2395 if (r
< 0 && r
!= -EOPNOTSUPP
)
2396 log_warning_errno(r
, "Failed to determine reboot-to-firmware state: %m");
2398 return sd_bus_message_append(reply
, "b", r
> 0);
2401 static int method_set_reboot_to_firmware_setup(
2402 sd_bus_message
*message
,
2404 sd_bus_error
*error
) {
2407 Manager
*m
= userdata
;
2412 r
= sd_bus_message_read(message
, "b", &b
);
2416 r
= bus_verify_polkit_async(message
,
2418 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2422 &m
->polkit_registry
,
2427 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2429 r
= efi_set_reboot_to_firmware(b
);
2433 return sd_bus_reply_method_return(message
, NULL
);
2436 static int method_can_reboot_to_firmware_setup(
2437 sd_bus_message
*message
,
2439 sd_bus_error
*error
) {
2444 Manager
*m
= userdata
;
2449 r
= efi_reboot_to_firmware_supported();
2451 if (r
!= -EOPNOTSUPP
)
2452 log_warning_errno(errno
, "Failed to determine whether reboot to firmware is supported: %m");
2454 return sd_bus_reply_method_return(message
, "s", "na");
2457 r
= bus_test_polkit(message
,
2459 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2470 result
= "challenge";
2474 return sd_bus_reply_method_return(message
, "s", result
);
2477 static int method_set_wall_message(
2478 sd_bus_message
*message
,
2480 sd_bus_error
*error
) {
2483 Manager
*m
= userdata
;
2485 int enable_wall_messages
;
2490 r
= sd_bus_message_read(message
, "sb", &wall_message
, &enable_wall_messages
);
2494 r
= bus_verify_polkit_async(message
,
2496 "org.freedesktop.login1.set-wall-message",
2500 &m
->polkit_registry
,
2505 return 1; /* Will call us back */
2507 r
= free_and_strdup(&m
->wall_message
, empty_to_null(wall_message
));
2511 m
->enable_wall_messages
= enable_wall_messages
;
2513 return sd_bus_reply_method_return(message
, NULL
);
2516 static int method_inhibit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2517 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2518 const char *who
, *why
, *what
, *mode
;
2519 _cleanup_free_
char *id
= NULL
;
2520 _cleanup_close_
int fifo_fd
= -1;
2521 Manager
*m
= userdata
;
2522 Inhibitor
*i
= NULL
;
2532 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2536 w
= inhibit_what_from_string(what
);
2538 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2540 mm
= inhibit_mode_from_string(mode
);
2542 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2544 /* Delay is only supported for shutdown/sleep */
2545 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2546 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2548 /* Don't allow taking delay locks while we are already
2549 * executing the operation. We shouldn't create the impression
2550 * that the lock was successful if the machine is about to go
2551 * down/suspend any moment. */
2552 if (m
->action_what
& w
)
2553 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2555 r
= bus_verify_polkit_async(
2558 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2559 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2560 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2561 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2562 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2563 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2564 "org.freedesktop.login1.inhibit-handle-lid-switch",
2568 &m
->polkit_registry
,
2573 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2575 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2579 r
= sd_bus_creds_get_euid(creds
, &uid
);
2583 r
= sd_bus_creds_get_pid(creds
, &pid
);
2587 if (hashmap_size(m
->inhibitors
) >= m
->inhibitors_max
)
2588 return sd_bus_error_setf(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Maximum number of inhibitors (%" PRIu64
") reached, refusing further inhibitors.", m
->inhibitors_max
);
2593 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2596 } while (hashmap_get(m
->inhibitors
, id
));
2598 r
= manager_add_inhibitor(m
, id
, &i
);
2606 i
->why
= strdup(why
);
2607 i
->who
= strdup(who
);
2609 if (!i
->why
|| !i
->who
) {
2614 fifo_fd
= inhibitor_create_fifo(i
);
2622 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2631 const sd_bus_vtable manager_vtable
[] = {
2632 SD_BUS_VTABLE_START(0),
2634 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2635 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2637 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2638 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2639 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2640 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2641 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2642 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2643 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2644 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2645 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2646 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2647 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2648 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2649 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2650 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2651 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2652 SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_ep
), SD_BUS_VTABLE_PROPERTY_CONST
),
2653 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2654 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2655 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2656 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2657 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2658 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2659 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2660 SD_BUS_PROPERTY("Docked", "b", property_get_docked
, 0, 0),
2661 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool
, offsetof(Manager
, remove_ipc
), SD_BUS_VTABLE_PROPERTY_CONST
),
2662 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size
, offsetof(Manager
, runtime_dir_size
), SD_BUS_VTABLE_PROPERTY_CONST
),
2663 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL
, offsetof(Manager
, inhibitors_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2664 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors
, 0, 0),
2665 SD_BUS_PROPERTY("SessionsMax", "t", NULL
, offsetof(Manager
, sessions_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2666 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions
, 0, 0),
2667 SD_BUS_PROPERTY("UserTasksMax", "t", NULL
, offsetof(Manager
, user_tasks_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2669 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2670 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2671 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2672 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2673 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2674 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2675 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2676 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2677 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2678 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2679 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2680 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2681 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2682 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2683 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2684 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2685 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2686 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2687 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2688 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2689 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2690 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2691 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2692 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2693 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2694 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2695 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2696 SD_BUS_METHOD("Halt", "b", NULL
, method_halt
, SD_BUS_VTABLE_UNPRIVILEGED
),
2697 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2698 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2699 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2700 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2701 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2702 SD_BUS_METHOD("CanHalt", NULL
, "s", method_can_halt
, SD_BUS_VTABLE_UNPRIVILEGED
),
2703 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2704 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2705 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2706 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2707 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2708 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2709 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2710 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2711 SD_BUS_METHOD("SetWallMessage", "sb", NULL
, method_set_wall_message
, SD_BUS_VTABLE_UNPRIVILEGED
),
2713 SD_BUS_SIGNAL("SessionNew", "so", 0),
2714 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2715 SD_BUS_SIGNAL("UserNew", "uo", 0),
2716 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2717 SD_BUS_SIGNAL("SeatNew", "so", 0),
2718 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2719 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2720 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2725 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2734 if (streq(result
, "done"))
2735 r
= session_send_create_reply(s
, NULL
);
2737 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
2739 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2740 r
= session_send_create_reply(s
, &e
);
2746 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2747 const char *path
, *result
, *unit
;
2748 Manager
*m
= userdata
;
2757 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2759 bus_log_parse_error(r
);
2763 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2764 log_info("Operation '%s' finished.", inhibit_what_to_string(m
->action_what
));
2766 /* Tell people that they now may take a lock again */
2767 (void) send_prepare_for(m
, m
->action_what
, false);
2769 m
->action_job
= mfree(m
->action_job
);
2770 m
->action_unit
= NULL
;
2775 session
= hashmap_get(m
->session_units
, unit
);
2776 if (session
&& streq_ptr(path
, session
->scope_job
)) {
2777 session
->scope_job
= mfree(session
->scope_job
);
2778 session_jobs_reply(session
, unit
, result
);
2780 session_save(session
);
2781 user_save(session
->user
);
2782 session_add_to_gc_queue(session
);
2785 user
= hashmap_get(m
->user_units
, unit
);
2787 (streq_ptr(path
, user
->service_job
) ||
2788 streq_ptr(path
, user
->slice_job
))) {
2790 if (streq_ptr(path
, user
->service_job
))
2791 user
->service_job
= mfree(user
->service_job
);
2793 if (streq_ptr(path
, user
->slice_job
))
2794 user
->slice_job
= mfree(user
->slice_job
);
2796 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
)
2797 session_jobs_reply(session
, unit
, result
);
2800 user_add_to_gc_queue(user
);
2806 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2807 const char *path
, *unit
;
2808 Manager
*m
= userdata
;
2816 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2818 bus_log_parse_error(r
);
2822 session
= hashmap_get(m
->session_units
, unit
);
2824 session_add_to_gc_queue(session
);
2826 user
= hashmap_get(m
->user_units
, unit
);
2828 user_add_to_gc_queue(user
);
2833 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2834 _cleanup_free_
char *unit
= NULL
;
2835 Manager
*m
= userdata
;
2844 path
= sd_bus_message_get_path(message
);
2848 r
= unit_name_from_dbus_path(path
, &unit
);
2849 if (r
== -EINVAL
) /* not a unit */
2856 session
= hashmap_get(m
->session_units
, unit
);
2858 session_add_to_gc_queue(session
);
2860 user
= hashmap_get(m
->user_units
, unit
);
2862 user_add_to_gc_queue(user
);
2867 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2868 Manager
*m
= userdata
;
2876 r
= sd_bus_message_read(message
, "b", &b
);
2878 bus_log_parse_error(r
);
2885 /* systemd finished reloading, let's recheck all our sessions */
2886 log_debug("System manager has been reloaded, rechecking sessions...");
2888 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2889 session_add_to_gc_queue(session
);
2894 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2899 l
= strv_from_stdarg_alloca(property
);
2901 return sd_bus_emit_properties_changed_strv(
2903 "/org/freedesktop/login1",
2904 "org.freedesktop.login1.Manager",
2908 static int strdup_job(sd_bus_message
*reply
, char **job
) {
2913 r
= sd_bus_message_read(reply
, "o", &j
);
2925 int manager_start_slice(
2928 const char *description
,
2932 sd_bus_error
*error
,
2935 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
2942 r
= sd_bus_message_new_method_call(
2945 "org.freedesktop.systemd1",
2946 "/org/freedesktop/systemd1",
2947 "org.freedesktop.systemd1.Manager",
2948 "StartTransientUnit");
2952 r
= sd_bus_message_append(m
, "ss", strempty(slice
), "fail");
2956 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2960 if (!isempty(description
)) {
2961 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2966 if (!isempty(after
)) {
2967 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2972 if (!isempty(after2
)) {
2973 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2978 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
2982 r
= sd_bus_message_close_container(m
);
2986 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2990 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2994 return strdup_job(reply
, job
);
2997 int manager_start_scope(
3002 const char *description
,
3006 sd_bus_error
*error
,
3009 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
3017 r
= sd_bus_message_new_method_call(
3020 "org.freedesktop.systemd1",
3021 "/org/freedesktop/systemd1",
3022 "org.freedesktop.systemd1.Manager",
3023 "StartTransientUnit");
3027 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
3031 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
3035 if (!isempty(slice
)) {
3036 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
3041 if (!isempty(description
)) {
3042 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
3047 if (!isempty(after
)) {
3048 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
3053 if (!isempty(after2
)) {
3054 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
3059 /* cgroup empty notification is not available in containers
3060 * currently. To make this less problematic, let's shorten the
3061 * stop timeout for sessions, so that we don't wait
3064 /* Make sure that the session shells are terminated with
3065 * SIGHUP since bash and friends tend to ignore SIGTERM */
3066 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
3070 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
3074 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
3078 r
= sd_bus_message_close_container(m
);
3082 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
3086 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
3090 return strdup_job(reply
, job
);
3093 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
3094 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3101 r
= sd_bus_call_method(
3103 "org.freedesktop.systemd1",
3104 "/org/freedesktop/systemd1",
3105 "org.freedesktop.systemd1.Manager",
3109 "ss", unit
, "replace");
3113 return strdup_job(reply
, job
);
3116 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
3117 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3124 r
= sd_bus_call_method(
3126 "org.freedesktop.systemd1",
3127 "/org/freedesktop/systemd1",
3128 "org.freedesktop.systemd1.Manager",
3132 "ss", unit
, "fail");
3134 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3135 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
3138 sd_bus_error_free(error
);
3145 return strdup_job(reply
, job
);
3148 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
3149 _cleanup_free_
char *path
= NULL
;
3155 path
= unit_dbus_path_from_name(scope
);
3159 r
= sd_bus_call_method(
3161 "org.freedesktop.systemd1",
3163 "org.freedesktop.systemd1.Scope",
3169 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3170 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
3171 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
3172 sd_bus_error_free(error
);
3182 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
3186 return sd_bus_call_method(
3188 "org.freedesktop.systemd1",
3189 "/org/freedesktop/systemd1",
3190 "org.freedesktop.systemd1.Manager",
3194 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
3197 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
3198 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3199 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3200 _cleanup_free_
char *path
= NULL
;
3207 path
= unit_dbus_path_from_name(unit
);
3211 r
= sd_bus_get_property(
3213 "org.freedesktop.systemd1",
3215 "org.freedesktop.systemd1.Unit",
3221 /* systemd might have droppped off momentarily, let's
3222 * not make this an error */
3223 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3224 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3227 /* If the unit is already unloaded then it's not
3229 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3230 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
3236 r
= sd_bus_message_read(reply
, "s", &state
);
3240 return !streq(state
, "inactive") && !streq(state
, "failed");
3243 int manager_job_is_active(Manager
*manager
, const char *path
) {
3244 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3245 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3251 r
= sd_bus_get_property(
3253 "org.freedesktop.systemd1",
3255 "org.freedesktop.systemd1.Job",
3261 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3262 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3265 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
3271 /* We don't actually care about the state really. The fact
3272 * that we could read the job state is enough for us */