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 "cgroup-util.h"
45 #include "selinux-util.h"
46 #include "sleep-config.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 static int get_sender_session(Manager
*m
, sd_bus_message
*message
, sd_bus_error
*error
, Session
**ret
) {
57 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
62 /* Get client login session. This is not what you are looking for these days,
63 * as apps may instead belong to a user service unit. This includes terminal
64 * emulators and hence command-line apps. */
65 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_AUGMENT
, &creds
);
69 r
= sd_bus_creds_get_session(creds
, &name
);
75 session
= hashmap_get(m
->sessions
, name
);
83 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
,
84 "Caller does not belong to any known session");
87 int manager_get_session_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Session
**ret
) {
95 return get_sender_session(m
, message
, error
, ret
);
97 session
= hashmap_get(m
->sessions
, name
);
99 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SESSION
, "No session '%s' known", name
);
105 static int get_sender_user(Manager
*m
, sd_bus_message
*message
, sd_bus_error
*error
, User
**ret
) {
107 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
112 /* Note that we get the owner UID of the session, not the actual client UID here! */
113 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
117 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
123 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
131 return sd_bus_error_setf(error
, BUS_ERROR_NO_USER_FOR_PID
, "Caller does not belong to any logged in user or lingering user");
134 int manager_get_user_from_creds(Manager
*m
, sd_bus_message
*message
, uid_t uid
, sd_bus_error
*error
, User
**ret
) {
141 if (!uid_is_valid(uid
))
142 return get_sender_user(m
, message
, error
, ret
);
144 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
146 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER
, "User ID "UID_FMT
" is not logged in or lingering", uid
);
152 int manager_get_seat_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Seat
**ret
) {
163 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
167 seat
= session
->seat
;
169 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "Session has no seat.");
171 seat
= hashmap_get(m
->seats
, name
);
173 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", name
);
180 static int property_get_idle_hint(
183 const char *interface
,
184 const char *property
,
185 sd_bus_message
*reply
,
187 sd_bus_error
*error
) {
189 Manager
*m
= userdata
;
195 return sd_bus_message_append(reply
, "b", manager_get_idle_hint(m
, NULL
) > 0);
198 static int property_get_idle_since_hint(
201 const char *interface
,
202 const char *property
,
203 sd_bus_message
*reply
,
205 sd_bus_error
*error
) {
207 Manager
*m
= userdata
;
208 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
214 manager_get_idle_hint(m
, &t
);
216 return sd_bus_message_append(reply
, "t", streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
);
219 static int property_get_inhibited(
222 const char *interface
,
223 const char *property
,
224 sd_bus_message
*reply
,
226 sd_bus_error
*error
) {
228 Manager
*m
= userdata
;
235 w
= manager_inhibit_what(m
, streq(property
, "BlockInhibited") ? INHIBIT_BLOCK
: INHIBIT_DELAY
);
237 return sd_bus_message_append(reply
, "s", inhibit_what_to_string(w
));
240 static int property_get_preparing(
243 const char *interface
,
244 const char *property
,
245 sd_bus_message
*reply
,
247 sd_bus_error
*error
) {
249 Manager
*m
= userdata
;
256 if (streq(property
, "PreparingForShutdown"))
257 b
= !!(m
->action_what
& INHIBIT_SHUTDOWN
);
259 b
= !!(m
->action_what
& INHIBIT_SLEEP
);
261 return sd_bus_message_append(reply
, "b", b
);
264 static int property_get_scheduled_shutdown(
267 const char *interface
,
268 const char *property
,
269 sd_bus_message
*reply
,
271 sd_bus_error
*error
) {
273 Manager
*m
= userdata
;
280 r
= sd_bus_message_open_container(reply
, 'r', "st");
284 r
= sd_bus_message_append(reply
, "st", m
->scheduled_shutdown_type
, m
->scheduled_shutdown_timeout
);
288 return sd_bus_message_close_container(reply
);
291 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action
, handle_action
, HandleAction
);
293 static int property_get_docked(
296 const char *interface
,
297 const char *property
,
298 sd_bus_message
*reply
,
300 sd_bus_error
*error
) {
302 Manager
*m
= userdata
;
308 return sd_bus_message_append(reply
, "b", manager_is_docked_or_external_displays(m
));
311 static int property_get_current_sessions(
314 const char *interface
,
315 const char *property
,
316 sd_bus_message
*reply
,
318 sd_bus_error
*error
) {
320 Manager
*m
= userdata
;
326 return sd_bus_message_append(reply
, "t", (uint64_t) hashmap_size(m
->sessions
));
329 static int property_get_current_inhibitors(
332 const char *interface
,
333 const char *property
,
334 sd_bus_message
*reply
,
336 sd_bus_error
*error
) {
338 Manager
*m
= userdata
;
344 return sd_bus_message_append(reply
, "t", (uint64_t) hashmap_size(m
->inhibitors
));
347 static int method_get_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
348 _cleanup_free_
char *p
= NULL
;
349 Manager
*m
= userdata
;
357 r
= sd_bus_message_read(message
, "s", &name
);
361 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
365 p
= session_bus_path(session
);
369 return sd_bus_reply_method_return(message
, "o", p
);
372 /* Get login session of a process. This is not what you are looking for these days,
373 * as apps may instead belong to a user service unit. This includes terminal
374 * emulators and hence command-line apps. */
375 static int method_get_session_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
376 _cleanup_free_
char *p
= NULL
;
377 Session
*session
= NULL
;
378 Manager
*m
= userdata
;
385 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
387 r
= sd_bus_message_read(message
, "u", &pid
);
394 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
398 r
= manager_get_session_by_pid(m
, pid
, &session
);
403 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
406 p
= session_bus_path(session
);
410 return sd_bus_reply_method_return(message
, "o", p
);
413 static int method_get_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
414 _cleanup_free_
char *p
= NULL
;
415 Manager
*m
= userdata
;
423 r
= sd_bus_message_read(message
, "u", &uid
);
427 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
431 p
= user_bus_path(user
);
435 return sd_bus_reply_method_return(message
, "o", p
);
438 static int method_get_user_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
439 _cleanup_free_
char *p
= NULL
;
440 Manager
*m
= userdata
;
448 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
450 r
= sd_bus_message_read(message
, "u", &pid
);
457 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
461 r
= manager_get_user_by_pid(m
, pid
, &user
);
465 return sd_bus_error_setf(error
, BUS_ERROR_NO_USER_FOR_PID
,
466 "PID "PID_FMT
" does not belong to any logged in user or lingering user",
470 p
= user_bus_path(user
);
474 return sd_bus_reply_method_return(message
, "o", p
);
477 static int method_get_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
478 _cleanup_free_
char *p
= NULL
;
479 Manager
*m
= userdata
;
487 r
= sd_bus_message_read(message
, "s", &name
);
491 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
495 p
= seat_bus_path(seat
);
499 return sd_bus_reply_method_return(message
, "o", p
);
502 static int method_list_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
503 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
504 Manager
*m
= userdata
;
512 r
= sd_bus_message_new_method_return(message
, &reply
);
516 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
520 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
521 _cleanup_free_
char *p
= NULL
;
523 p
= session_bus_path(session
);
527 r
= sd_bus_message_append(reply
, "(susso)",
529 (uint32_t) session
->user
->uid
,
531 session
->seat
? session
->seat
->id
: "",
537 r
= sd_bus_message_close_container(reply
);
541 return sd_bus_send(NULL
, reply
, NULL
);
544 static int method_list_users(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
545 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
546 Manager
*m
= userdata
;
554 r
= sd_bus_message_new_method_return(message
, &reply
);
558 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
562 HASHMAP_FOREACH(user
, m
->users
, i
) {
563 _cleanup_free_
char *p
= NULL
;
565 p
= user_bus_path(user
);
569 r
= sd_bus_message_append(reply
, "(uso)",
570 (uint32_t) user
->uid
,
577 r
= sd_bus_message_close_container(reply
);
581 return sd_bus_send(NULL
, reply
, NULL
);
584 static int method_list_seats(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
585 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
586 Manager
*m
= userdata
;
594 r
= sd_bus_message_new_method_return(message
, &reply
);
598 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
602 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
603 _cleanup_free_
char *p
= NULL
;
605 p
= seat_bus_path(seat
);
609 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
614 r
= sd_bus_message_close_container(reply
);
618 return sd_bus_send(NULL
, reply
, NULL
);
621 static int method_list_inhibitors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
622 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
623 Manager
*m
= userdata
;
624 Inhibitor
*inhibitor
;
631 r
= sd_bus_message_new_method_return(message
, &reply
);
635 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
639 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
641 r
= sd_bus_message_append(reply
, "(ssssuu)",
642 strempty(inhibit_what_to_string(inhibitor
->what
)),
643 strempty(inhibitor
->who
),
644 strempty(inhibitor
->why
),
645 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
646 (uint32_t) inhibitor
->uid
,
647 (uint32_t) inhibitor
->pid
);
652 r
= sd_bus_message_close_container(reply
);
656 return sd_bus_send(NULL
, reply
, NULL
);
659 static int method_create_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
660 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
661 _cleanup_free_
char *id
= NULL
;
662 Session
*session
= NULL
;
663 uint32_t audit_id
= 0;
664 Manager
*m
= userdata
;
678 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
679 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
681 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
685 if (!uid_is_valid(uid
))
686 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid UID");
687 if (leader
< 0 || leader
== 1 || leader
== getpid_cached())
688 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
691 t
= _SESSION_TYPE_INVALID
;
693 t
= session_type_from_string(type
);
695 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
699 c
= _SESSION_CLASS_INVALID
;
701 c
= session_class_from_string(class);
703 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
706 if (isempty(desktop
))
709 if (!string_is_safe(desktop
))
710 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
716 seat
= hashmap_get(m
->seats
, cseat
);
718 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
721 if (tty_is_vc(tty
)) {
726 else if (seat
!= m
->seat0
)
727 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
);
729 v
= vtnr_from_tty(tty
);
731 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
735 else if (vtnr
!= (uint32_t) v
)
736 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
738 } else if (tty_is_console(tty
)) {
742 else if (seat
!= m
->seat0
)
743 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
746 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
750 if (seat_has_vts(seat
)) {
751 if (vtnr
<= 0 || vtnr
> 63)
752 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
755 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
759 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
763 if (t
== _SESSION_TYPE_INVALID
) {
764 if (!isempty(display
))
766 else if (!isempty(tty
))
769 t
= SESSION_UNSPECIFIED
;
772 if (c
== _SESSION_CLASS_INVALID
) {
773 if (t
== SESSION_UNSPECIFIED
)
774 c
= SESSION_BACKGROUND
;
780 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
782 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
786 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
791 /* Check if we are already in a logind session. Or if we are in user@.service which is a special PAM session
792 * that avoids creating a logind session. */
793 r
= manager_get_user_by_pid(m
, leader
, NULL
);
797 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already running in a session or user slice");
800 * Old gdm and lightdm start the user-session on the same VT as
801 * the greeter session. But they destroy the greeter session
802 * after the user-session and want the user-session to take
803 * over the VT. We need to support this for
804 * backwards-compatibility, so make sure we allow new sessions
805 * on a VT that a greeter is running on. Furthermore, to allow
806 * re-logins, we have to allow a greeter to take over a used VT for
807 * the exact same reasons.
809 if (c
!= SESSION_GREETER
&&
811 vtnr
< m
->seat0
->position_count
&&
812 m
->seat0
->positions
[vtnr
] &&
813 m
->seat0
->positions
[vtnr
]->class != SESSION_GREETER
)
814 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already occupied by a session");
816 if (hashmap_size(m
->sessions
) >= m
->sessions_max
)
817 return sd_bus_error_setf(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Maximum number of sessions (%" PRIu64
") reached, refusing further sessions.", m
->sessions_max
);
819 (void) audit_session_from_pid(leader
, &audit_id
);
820 if (audit_session_is_valid(audit_id
)) {
821 /* Keep our session IDs and the audit session IDs in sync */
823 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
826 /* Wut? There's already a session by this name and we
827 * didn't find it above? Weird, then let's not trust
828 * the audit data and let's better register a new
830 if (hashmap_get(m
->sessions
, id
)) {
831 log_warning("Existing logind session ID %s used by new audit session, ignoring.", id
);
832 audit_id
= AUDIT_SESSION_INVALID
;
841 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
844 } while (hashmap_get(m
->sessions
, id
));
847 r
= manager_add_user_by_uid(m
, uid
, &user
);
851 r
= manager_add_session(m
, id
, &session
);
855 session_set_user(session
, user
);
857 session
->leader
= leader
;
858 session
->audit_id
= audit_id
;
861 session
->remote
= remote
;
862 session
->vtnr
= vtnr
;
865 session
->tty
= strdup(tty
);
872 if (!isempty(display
)) {
873 session
->display
= strdup(display
);
874 if (!session
->display
) {
880 if (!isempty(remote_user
)) {
881 session
->remote_user
= strdup(remote_user
);
882 if (!session
->remote_user
) {
888 if (!isempty(remote_host
)) {
889 session
->remote_host
= strdup(remote_host
);
890 if (!session
->remote_host
) {
896 if (!isempty(service
)) {
897 session
->service
= strdup(service
);
898 if (!session
->service
) {
904 if (!isempty(desktop
)) {
905 session
->desktop
= strdup(desktop
);
906 if (!session
->desktop
) {
913 r
= seat_attach_session(seat
, session
);
918 r
= session_start(session
);
922 session
->create_message
= sd_bus_message_ref(message
);
924 /* Now, let's wait until the slice unit and stuff got created. We send the reply back from
925 * session_send_create_reply(). */
931 session_add_to_gc_queue(session
);
934 user_add_to_gc_queue(user
);
939 static int method_release_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
940 Manager
*m
= userdata
;
948 r
= sd_bus_message_read(message
, "s", &name
);
952 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
956 r
= session_release(session
);
960 return sd_bus_reply_method_return(message
, NULL
);
963 static int method_activate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
964 Manager
*m
= userdata
;
972 r
= sd_bus_message_read(message
, "s", &name
);
976 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
980 return bus_session_method_activate(message
, session
, error
);
983 static int method_activate_session_on_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
984 const char *session_name
, *seat_name
;
985 Manager
*m
= userdata
;
993 /* Same as ActivateSession() but refuses to work if
994 * the seat doesn't match */
996 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
1000 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
1004 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
1008 if (session
->seat
!= seat
)
1009 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
1011 r
= session_activate(session
);
1015 return sd_bus_reply_method_return(message
, NULL
);
1018 static int method_lock_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1019 Manager
*m
= userdata
;
1027 r
= sd_bus_message_read(message
, "s", &name
);
1031 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1035 return bus_session_method_lock(message
, session
, error
);
1038 static int method_lock_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1039 Manager
*m
= userdata
;
1045 r
= bus_verify_polkit_async(
1048 "org.freedesktop.login1.lock-sessions",
1052 &m
->polkit_registry
,
1057 return 1; /* Will call us back */
1059 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
1063 return sd_bus_reply_method_return(message
, NULL
);
1066 static int method_kill_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1068 Manager
*m
= userdata
;
1075 r
= sd_bus_message_read(message
, "s", &name
);
1079 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1083 return bus_session_method_kill(message
, session
, error
);
1086 static int method_kill_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1087 Manager
*m
= userdata
;
1095 r
= sd_bus_message_read(message
, "u", &uid
);
1099 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1103 return bus_user_method_kill(message
, user
, error
);
1106 static int method_terminate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1107 Manager
*m
= userdata
;
1115 r
= sd_bus_message_read(message
, "s", &name
);
1119 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1123 return bus_session_method_terminate(message
, session
, error
);
1126 static int method_terminate_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1127 Manager
*m
= userdata
;
1135 r
= sd_bus_message_read(message
, "u", &uid
);
1139 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1143 return bus_user_method_terminate(message
, user
, error
);
1146 static int method_terminate_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1147 Manager
*m
= userdata
;
1155 r
= sd_bus_message_read(message
, "s", &name
);
1159 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
1163 return bus_seat_method_terminate(message
, seat
, error
);
1166 static int method_set_user_linger(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1167 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1168 _cleanup_free_
char *cc
= NULL
;
1169 Manager
*m
= userdata
;
1170 int r
, b
, interactive
;
1173 uint32_t uid
, auth_uid
;
1178 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1182 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|
1183 SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1187 if (!uid_is_valid(uid
)) {
1188 /* Note that we get the owner UID of the session or user unit,
1189 * not the actual client UID here! */
1190 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1195 /* owner_uid is racy, so for authorization we must use euid */
1196 r
= sd_bus_creds_get_euid(creds
, &auth_uid
);
1203 return errno
> 0 ? -errno
: -ENOENT
;
1205 r
= bus_verify_polkit_async(
1208 uid
== auth_uid
? "org.freedesktop.login1.set-self-linger" :
1209 "org.freedesktop.login1.set-user-linger",
1213 &m
->polkit_registry
,
1218 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1220 mkdir_p_label("/var/lib/systemd", 0755);
1222 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, MKDIR_WARN_MODE
);
1226 cc
= cescape(pw
->pw_name
);
1230 path
= strjoina("/var/lib/systemd/linger/", cc
);
1238 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1245 if (r
< 0 && errno
!= ENOENT
)
1248 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1250 user_add_to_gc_queue(u
);
1253 return sd_bus_reply_method_return(message
, NULL
);
1256 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1257 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1258 struct udev_list_entry
*first
, *item
;
1263 e
= udev_enumerate_new(m
->udev
);
1268 r
= udev_enumerate_add_match_parent(e
, d
);
1273 r
= udev_enumerate_scan_devices(e
);
1277 first
= udev_enumerate_get_list_entry(e
);
1278 udev_list_entry_foreach(item
, first
) {
1279 _cleanup_free_
char *t
= NULL
;
1282 p
= udev_list_entry_get_name(item
);
1284 t
= strappend(p
, "/uevent");
1288 (void) write_string_file(t
, "change", 0);
1294 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1295 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1296 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1297 const char *id_for_seat
;
1304 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1308 if (!udev_device_has_tag(d
, "seat"))
1311 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1315 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1318 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1321 mkdir_p_label("/etc/udev/rules.d", 0755);
1322 r
= write_string_file_atomic_label(file
, rule
);
1326 return trigger_device(m
, d
);
1329 static int flush_devices(Manager
*m
) {
1330 _cleanup_closedir_
DIR *d
;
1334 d
= opendir("/etc/udev/rules.d");
1336 if (errno
!= ENOENT
)
1337 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1341 FOREACH_DIRENT_ALL(de
, d
, break) {
1342 if (!dirent_is_file(de
))
1345 if (!startswith(de
->d_name
, "72-seat-"))
1348 if (!endswith(de
->d_name
, ".rules"))
1351 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1352 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1356 return trigger_device(m
, NULL
);
1359 static int method_attach_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1360 const char *sysfs
, *seat
;
1361 Manager
*m
= userdata
;
1367 r
= sd_bus_message_read(message
, "ssb", &seat
, &sysfs
, &interactive
);
1371 if (!path_startswith(sysfs
, "/sys"))
1372 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not in /sys", sysfs
);
1374 if (!seat_name_is_valid(seat
))
1375 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat %s is not valid", seat
);
1377 r
= bus_verify_polkit_async(
1380 "org.freedesktop.login1.attach-device",
1384 &m
->polkit_registry
,
1389 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1391 r
= attach_device(m
, seat
, sysfs
);
1395 return sd_bus_reply_method_return(message
, NULL
);
1398 static int method_flush_devices(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1399 Manager
*m
= userdata
;
1405 r
= sd_bus_message_read(message
, "b", &interactive
);
1409 r
= bus_verify_polkit_async(
1412 "org.freedesktop.login1.flush-devices",
1416 &m
->polkit_registry
,
1421 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1423 r
= flush_devices(m
);
1427 return sd_bus_reply_method_return(message
, NULL
);
1430 static int have_multiple_sessions(
1439 /* Check for other users' sessions. Greeter sessions do not
1440 * count, and non-login sessions do not count either. */
1441 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1442 if (session
->class == SESSION_USER
&&
1443 session
->user
->uid
!= uid
)
1449 static int bus_manager_log_shutdown(
1451 const char *unit_name
) {
1458 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1459 p
= "MESSAGE=System is powering down";
1460 q
= "SHUTDOWN=power-off";
1461 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1462 p
= "MESSAGE=System is rebooting";
1463 q
= "SHUTDOWN=reboot";
1464 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1465 p
= "MESSAGE=System is halting";
1466 q
= "SHUTDOWN=halt";
1467 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1468 p
= "MESSAGE=System is rebooting with kexec";
1469 q
= "SHUTDOWN=kexec";
1471 p
= "MESSAGE=System is shutting down";
1475 if (isempty(m
->wall_message
))
1476 p
= strjoina(p
, ".");
1478 p
= strjoina(p
, " (", m
->wall_message
, ").");
1480 return log_struct(LOG_NOTICE
,
1481 "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR
,
1487 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1488 Manager
*m
= userdata
;
1493 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1497 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1502 if (until
<= now(CLOCK_MONOTONIC
))
1505 /* We want to ignore the lid switch for a while after each
1506 * suspend, and after boot-up. Hence let's install a timer for
1507 * this. As long as the event source exists we ignore the lid
1510 if (m
->lid_switch_ignore_event_source
) {
1513 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1520 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1522 r
= sd_event_add_time(
1524 &m
->lid_switch_ignore_event_source
,
1527 lid_switch_ignore_handler
, m
);
1532 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1534 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1535 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1536 [INHIBIT_SLEEP
] = "PrepareForSleep"
1539 int active
= _active
;
1543 assert(w
< _INHIBIT_WHAT_MAX
);
1544 assert(signal_name
[w
]);
1546 return sd_bus_emit_signal(m
->bus
,
1547 "/org/freedesktop/login1",
1548 "org.freedesktop.login1.Manager",
1554 static int execute_shutdown_or_sleep(
1557 const char *unit_name
,
1558 sd_bus_error
*error
) {
1560 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1567 assert(w
< _INHIBIT_WHAT_MAX
);
1570 if (w
== INHIBIT_SHUTDOWN
)
1571 bus_manager_log_shutdown(m
, unit_name
);
1573 r
= sd_bus_call_method(
1575 "org.freedesktop.systemd1",
1576 "/org/freedesktop/systemd1",
1577 "org.freedesktop.systemd1.Manager",
1581 "ss", unit_name
, "replace-irreversibly");
1585 r
= sd_bus_message_read(reply
, "o", &p
);
1595 m
->action_unit
= unit_name
;
1596 free(m
->action_job
);
1600 /* Make sure the lid switch is ignored for a while */
1601 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1606 /* Tell people that they now may take a lock again */
1607 (void) send_prepare_for(m
, w
, false);
1612 int manager_dispatch_delayed(Manager
*manager
, bool timeout
) {
1614 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1615 Inhibitor
*offending
= NULL
;
1620 if (manager
->action_what
== 0 || manager
->action_job
)
1623 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1624 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1629 (void) get_process_comm(offending
->pid
, &comm
);
1630 u
= uid_to_name(offending
->uid
);
1632 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1633 offending
->uid
, strna(u
),
1634 offending
->pid
, strna(comm
));
1637 /* Actually do the operation */
1638 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1640 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1641 bus_error_message(&error
, r
));
1643 manager
->action_unit
= NULL
;
1644 manager
->action_what
= 0;
1651 static int manager_inhibit_timeout_handler(
1656 Manager
*manager
= userdata
;
1660 assert(manager
->inhibit_timeout_source
== s
);
1662 r
= manager_dispatch_delayed(manager
, true);
1663 return (r
< 0) ? r
: 0;
1666 static int delay_shutdown_or_sleep(
1669 const char *unit_name
) {
1676 assert(w
< _INHIBIT_WHAT_MAX
);
1679 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1681 if (m
->inhibit_timeout_source
) {
1682 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1684 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1686 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1688 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1690 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1691 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1696 m
->action_unit
= unit_name
;
1702 int bus_manager_shutdown_or_sleep_now_or_later(
1704 const char *unit_name
,
1706 sd_bus_error
*error
) {
1714 assert(w
<= _INHIBIT_WHAT_MAX
);
1715 assert(!m
->action_job
);
1717 /* Tell everybody to prepare for shutdown/sleep */
1718 (void) send_prepare_for(m
, w
, true);
1721 m
->inhibit_delay_max
> 0 &&
1722 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1725 /* Shutdown is delayed, keep in mind what we
1726 * want to do, and start a timeout */
1727 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1729 /* Shutdown is not delayed, execute it
1731 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1736 static int verify_shutdown_creds(
1738 sd_bus_message
*message
,
1742 const char *action_multiple_sessions
,
1743 const char *action_ignore_inhibit
,
1744 sd_bus_error
*error
) {
1746 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1747 bool multiple_sessions
, blocked
;
1754 assert(w
<= _INHIBIT_WHAT_MAX
);
1756 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1760 r
= sd_bus_creds_get_euid(creds
, &uid
);
1764 r
= have_multiple_sessions(m
, uid
);
1768 multiple_sessions
= r
> 0;
1769 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1771 if (multiple_sessions
&& action_multiple_sessions
) {
1772 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1776 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1779 if (blocked
&& action_ignore_inhibit
) {
1780 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1784 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1787 if (!multiple_sessions
&& !blocked
&& action
) {
1788 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1792 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1798 static int method_do_shutdown_or_sleep(
1800 sd_bus_message
*message
,
1801 const char *unit_name
,
1804 const char *action_multiple_sessions
,
1805 const char *action_ignore_inhibit
,
1806 const char *sleep_verb
,
1807 sd_bus_error
*error
) {
1815 assert(w
<= _INHIBIT_WHAT_MAX
);
1817 r
= sd_bus_message_read(message
, "b", &interactive
);
1821 /* Don't allow multiple jobs being executed at the same time */
1823 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1826 r
= can_sleep(sleep_verb
);
1831 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1834 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1835 action_ignore_inhibit
, error
);
1839 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1843 return sd_bus_reply_method_return(message
, NULL
);
1846 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1847 Manager
*m
= userdata
;
1849 return method_do_shutdown_or_sleep(
1851 SPECIAL_POWEROFF_TARGET
,
1853 "org.freedesktop.login1.power-off",
1854 "org.freedesktop.login1.power-off-multiple-sessions",
1855 "org.freedesktop.login1.power-off-ignore-inhibit",
1860 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1861 Manager
*m
= userdata
;
1863 return method_do_shutdown_or_sleep(
1865 SPECIAL_REBOOT_TARGET
,
1867 "org.freedesktop.login1.reboot",
1868 "org.freedesktop.login1.reboot-multiple-sessions",
1869 "org.freedesktop.login1.reboot-ignore-inhibit",
1874 static int method_halt(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1875 Manager
*m
= userdata
;
1877 return method_do_shutdown_or_sleep(
1879 SPECIAL_HALT_TARGET
,
1881 "org.freedesktop.login1.halt",
1882 "org.freedesktop.login1.halt-multiple-sessions",
1883 "org.freedesktop.login1.halt-ignore-inhibit",
1888 static int method_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1889 Manager
*m
= userdata
;
1891 return method_do_shutdown_or_sleep(
1893 SPECIAL_SUSPEND_TARGET
,
1895 "org.freedesktop.login1.suspend",
1896 "org.freedesktop.login1.suspend-multiple-sessions",
1897 "org.freedesktop.login1.suspend-ignore-inhibit",
1902 static int method_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1903 Manager
*m
= userdata
;
1905 return method_do_shutdown_or_sleep(
1907 SPECIAL_HIBERNATE_TARGET
,
1909 "org.freedesktop.login1.hibernate",
1910 "org.freedesktop.login1.hibernate-multiple-sessions",
1911 "org.freedesktop.login1.hibernate-ignore-inhibit",
1916 static int method_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1917 Manager
*m
= userdata
;
1919 return method_do_shutdown_or_sleep(
1921 SPECIAL_HYBRID_SLEEP_TARGET
,
1923 "org.freedesktop.login1.hibernate",
1924 "org.freedesktop.login1.hibernate-multiple-sessions",
1925 "org.freedesktop.login1.hibernate-ignore-inhibit",
1930 static int method_suspend_then_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1931 Manager
*m
= userdata
;
1933 return method_do_shutdown_or_sleep(
1935 SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET
,
1937 "org.freedesktop.login1.hibernate",
1938 "org.freedesktop.login1.hibernate-multiple-sessions",
1939 "org.freedesktop.login1.hibernate-ignore-inhibit",
1944 static int nologin_timeout_handler(
1949 Manager
*m
= userdata
;
1951 log_info("Creating /run/nologin, blocking further logins...");
1954 create_shutdown_run_nologin_or_warn() >= 0;
1959 static int update_schedule_file(Manager
*m
) {
1960 _cleanup_free_
char *temp_path
= NULL
;
1961 _cleanup_fclose_
FILE *f
= NULL
;
1966 r
= mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE
);
1968 return log_error_errno(r
, "Failed to create shutdown subdirectory: %m");
1970 r
= fopen_temporary("/run/systemd/shutdown/scheduled", &f
, &temp_path
);
1972 return log_error_errno(r
, "Failed to save information about scheduled shutdowns: %m");
1974 (void) fchmod(fileno(f
), 0644);
1980 m
->scheduled_shutdown_timeout
,
1981 m
->enable_wall_messages
,
1982 m
->scheduled_shutdown_type
);
1984 if (!isempty(m
->wall_message
)) {
1985 _cleanup_free_
char *t
;
1987 t
= cescape(m
->wall_message
);
1993 fprintf(f
, "WALL_MESSAGE=%s\n", t
);
1996 r
= fflush_and_check(f
);
2000 if (rename(temp_path
, "/run/systemd/shutdown/scheduled") < 0) {
2008 (void) unlink(temp_path
);
2009 (void) unlink("/run/systemd/shutdown/scheduled");
2011 return log_error_errno(r
, "Failed to write information about scheduled shutdowns: %m");
2014 static void reset_scheduled_shutdown(Manager
*m
) {
2017 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2018 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
2019 m
->nologin_timeout_source
= sd_event_source_unref(m
->nologin_timeout_source
);
2021 m
->scheduled_shutdown_type
= mfree(m
->scheduled_shutdown_type
);
2022 m
->scheduled_shutdown_timeout
= 0;
2023 m
->shutdown_dry_run
= false;
2025 if (m
->unlink_nologin
) {
2026 (void) unlink_or_warn("/run/nologin");
2027 m
->unlink_nologin
= false;
2030 (void) unlink("/run/systemd/shutdown/scheduled");
2033 static int manager_scheduled_shutdown_handler(
2038 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2039 Manager
*m
= userdata
;
2045 if (isempty(m
->scheduled_shutdown_type
))
2048 if (streq(m
->scheduled_shutdown_type
, "poweroff"))
2049 target
= SPECIAL_POWEROFF_TARGET
;
2050 else if (streq(m
->scheduled_shutdown_type
, "reboot"))
2051 target
= SPECIAL_REBOOT_TARGET
;
2052 else if (streq(m
->scheduled_shutdown_type
, "halt"))
2053 target
= SPECIAL_HALT_TARGET
;
2055 assert_not_reached("unexpected shutdown type");
2057 /* Don't allow multiple jobs being executed at the same time */
2058 if (m
->action_what
) {
2060 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target
);
2064 if (m
->shutdown_dry_run
) {
2065 /* We do not process delay inhibitors here. Otherwise, we
2066 * would have to be considered "in progress" (like the check
2067 * above) for some seconds after our admin has seen the final
2070 bus_manager_log_shutdown(m
, target
);
2071 log_info("Running in dry run, suppressing action.");
2072 reset_scheduled_shutdown(m
);
2077 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, target
, INHIBIT_SHUTDOWN
, &error
);
2079 log_error_errno(r
, "Scheduled shutdown to %s failed: %m", target
);
2086 reset_scheduled_shutdown(m
);
2090 static int method_schedule_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2091 Manager
*m
= userdata
;
2092 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2093 const char *action_multiple_sessions
= NULL
;
2094 const char *action_ignore_inhibit
= NULL
;
2095 const char *action
= NULL
;
2099 bool dry_run
= false;
2104 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
2108 if (startswith(type
, "dry-")) {
2113 if (streq(type
, "poweroff")) {
2114 action
= "org.freedesktop.login1.power-off";
2115 action_multiple_sessions
= "org.freedesktop.login1.power-off-multiple-sessions";
2116 action_ignore_inhibit
= "org.freedesktop.login1.power-off-ignore-inhibit";
2117 } else if (streq(type
, "reboot")) {
2118 action
= "org.freedesktop.login1.reboot";
2119 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
2120 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
2121 } else if (streq(type
, "halt")) {
2122 action
= "org.freedesktop.login1.halt";
2123 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
2124 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
2126 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
2128 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
2129 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
2133 if (m
->scheduled_shutdown_timeout_source
) {
2134 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
2136 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
2138 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
2140 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
2142 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
2143 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
2145 return log_error_errno(r
, "sd_event_add_time() failed: %m");
2148 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
2150 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2154 m
->shutdown_dry_run
= dry_run
;
2156 if (m
->nologin_timeout_source
) {
2157 r
= sd_event_source_set_time(m
->nologin_timeout_source
, elapse
);
2159 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
2161 r
= sd_event_source_set_enabled(m
->nologin_timeout_source
, SD_EVENT_ONESHOT
);
2163 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
2165 r
= sd_event_add_time(m
->event
, &m
->nologin_timeout_source
,
2166 CLOCK_REALTIME
, elapse
- 5 * USEC_PER_MINUTE
, 0, nologin_timeout_handler
, m
);
2168 return log_error_errno(r
, "sd_event_add_time() failed: %m");
2171 m
->scheduled_shutdown_timeout
= elapse
;
2173 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2175 const char *tty
= NULL
;
2177 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
2178 (void) sd_bus_creds_get_tty(creds
, &tty
);
2180 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
2182 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2187 r
= manager_setup_wall_message_timer(m
);
2191 r
= update_schedule_file(m
);
2195 return sd_bus_reply_method_return(message
, NULL
);
2198 static int method_cancel_scheduled_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2199 Manager
*m
= userdata
;
2205 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
2206 reset_scheduled_shutdown(m
);
2209 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2210 const char *tty
= NULL
;
2214 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2216 (void) sd_bus_creds_get_uid(creds
, &uid
);
2217 (void) sd_bus_creds_get_tty(creds
, &tty
);
2220 utmp_wall("The system shutdown has been cancelled",
2221 uid_to_name(uid
), tty
, logind_wall_tty_filter
, m
);
2224 return sd_bus_reply_method_return(message
, "b", cancelled
);
2227 static int method_can_shutdown_or_sleep(
2229 sd_bus_message
*message
,
2232 const char *action_multiple_sessions
,
2233 const char *action_ignore_inhibit
,
2234 const char *sleep_verb
,
2235 sd_bus_error
*error
) {
2237 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2238 bool multiple_sessions
, challenge
, blocked
;
2239 const char *result
= NULL
;
2246 assert(w
<= _INHIBIT_WHAT_MAX
);
2248 assert(action_multiple_sessions
);
2249 assert(action_ignore_inhibit
);
2252 r
= can_sleep(sleep_verb
);
2256 return sd_bus_reply_method_return(message
, "s", "na");
2259 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
2263 r
= sd_bus_creds_get_euid(creds
, &uid
);
2267 r
= have_multiple_sessions(m
, uid
);
2271 multiple_sessions
= r
> 0;
2272 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
2274 if (multiple_sessions
) {
2275 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, UID_INVALID
, &challenge
, error
);
2282 result
= "challenge";
2288 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, UID_INVALID
, &challenge
, error
);
2292 if (r
> 0 && !result
)
2294 else if (challenge
&& (!result
|| streq(result
, "yes")))
2295 result
= "challenge";
2300 if (!multiple_sessions
&& !blocked
) {
2301 /* If neither inhibit nor multiple sessions
2302 * apply then just check the normal policy */
2304 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, NULL
, UID_INVALID
, &challenge
, error
);
2311 result
= "challenge";
2316 return sd_bus_reply_method_return(message
, "s", result
);
2319 static int method_can_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2320 Manager
*m
= userdata
;
2322 return method_can_shutdown_or_sleep(
2325 "org.freedesktop.login1.power-off",
2326 "org.freedesktop.login1.power-off-multiple-sessions",
2327 "org.freedesktop.login1.power-off-ignore-inhibit",
2332 static int method_can_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2333 Manager
*m
= userdata
;
2335 return method_can_shutdown_or_sleep(
2338 "org.freedesktop.login1.reboot",
2339 "org.freedesktop.login1.reboot-multiple-sessions",
2340 "org.freedesktop.login1.reboot-ignore-inhibit",
2345 static int method_can_halt(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2346 Manager
*m
= userdata
;
2348 return method_can_shutdown_or_sleep(
2351 "org.freedesktop.login1.halt",
2352 "org.freedesktop.login1.halt-multiple-sessions",
2353 "org.freedesktop.login1.halt-ignore-inhibit",
2358 static int method_can_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2359 Manager
*m
= userdata
;
2361 return method_can_shutdown_or_sleep(
2364 "org.freedesktop.login1.suspend",
2365 "org.freedesktop.login1.suspend-multiple-sessions",
2366 "org.freedesktop.login1.suspend-ignore-inhibit",
2371 static int method_can_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2372 Manager
*m
= userdata
;
2374 return method_can_shutdown_or_sleep(
2377 "org.freedesktop.login1.hibernate",
2378 "org.freedesktop.login1.hibernate-multiple-sessions",
2379 "org.freedesktop.login1.hibernate-ignore-inhibit",
2384 static int method_can_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2385 Manager
*m
= userdata
;
2387 return method_can_shutdown_or_sleep(
2390 "org.freedesktop.login1.hibernate",
2391 "org.freedesktop.login1.hibernate-multiple-sessions",
2392 "org.freedesktop.login1.hibernate-ignore-inhibit",
2397 static int method_can_suspend_then_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2398 Manager
*m
= userdata
;
2400 return method_can_shutdown_or_sleep(
2403 "org.freedesktop.login1.hibernate",
2404 "org.freedesktop.login1.hibernate-multiple-sessions",
2405 "org.freedesktop.login1.hibernate-ignore-inhibit",
2406 "suspend-then-hibernate",
2410 static int property_get_reboot_to_firmware_setup(
2413 const char *interface
,
2414 const char *property
,
2415 sd_bus_message
*reply
,
2417 sd_bus_error
*error
) {
2424 r
= efi_get_reboot_to_firmware();
2425 if (r
< 0 && r
!= -EOPNOTSUPP
)
2426 log_warning_errno(r
, "Failed to determine reboot-to-firmware state: %m");
2428 return sd_bus_message_append(reply
, "b", r
> 0);
2431 static int method_set_reboot_to_firmware_setup(
2432 sd_bus_message
*message
,
2434 sd_bus_error
*error
) {
2437 Manager
*m
= userdata
;
2442 r
= sd_bus_message_read(message
, "b", &b
);
2446 r
= bus_verify_polkit_async(message
,
2448 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2452 &m
->polkit_registry
,
2457 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2459 r
= efi_set_reboot_to_firmware(b
);
2463 return sd_bus_reply_method_return(message
, NULL
);
2466 static int method_can_reboot_to_firmware_setup(
2467 sd_bus_message
*message
,
2469 sd_bus_error
*error
) {
2474 Manager
*m
= userdata
;
2479 r
= efi_reboot_to_firmware_supported();
2481 if (r
!= -EOPNOTSUPP
)
2482 log_warning_errno(errno
, "Failed to determine whether reboot to firmware is supported: %m");
2484 return sd_bus_reply_method_return(message
, "s", "na");
2487 r
= bus_test_polkit(message
,
2489 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2500 result
= "challenge";
2504 return sd_bus_reply_method_return(message
, "s", result
);
2507 static int method_set_wall_message(
2508 sd_bus_message
*message
,
2510 sd_bus_error
*error
) {
2513 Manager
*m
= userdata
;
2515 int enable_wall_messages
;
2520 r
= sd_bus_message_read(message
, "sb", &wall_message
, &enable_wall_messages
);
2524 r
= bus_verify_polkit_async(message
,
2526 "org.freedesktop.login1.set-wall-message",
2530 &m
->polkit_registry
,
2535 return 1; /* Will call us back */
2537 r
= free_and_strdup(&m
->wall_message
, empty_to_null(wall_message
));
2541 m
->enable_wall_messages
= enable_wall_messages
;
2543 return sd_bus_reply_method_return(message
, NULL
);
2546 static int method_inhibit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2547 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2548 const char *who
, *why
, *what
, *mode
;
2549 _cleanup_free_
char *id
= NULL
;
2550 _cleanup_close_
int fifo_fd
= -1;
2551 Manager
*m
= userdata
;
2552 Inhibitor
*i
= NULL
;
2562 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2566 w
= inhibit_what_from_string(what
);
2568 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2570 mm
= inhibit_mode_from_string(mode
);
2572 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2574 /* Delay is only supported for shutdown/sleep */
2575 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2576 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2578 /* Don't allow taking delay locks while we are already
2579 * executing the operation. We shouldn't create the impression
2580 * that the lock was successful if the machine is about to go
2581 * down/suspend any moment. */
2582 if (m
->action_what
& w
)
2583 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2585 r
= bus_verify_polkit_async(
2588 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2589 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2590 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2591 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2592 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2593 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2594 "org.freedesktop.login1.inhibit-handle-lid-switch",
2598 &m
->polkit_registry
,
2603 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2605 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2609 r
= sd_bus_creds_get_euid(creds
, &uid
);
2613 r
= sd_bus_creds_get_pid(creds
, &pid
);
2617 if (hashmap_size(m
->inhibitors
) >= m
->inhibitors_max
)
2618 return sd_bus_error_setf(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Maximum number of inhibitors (%" PRIu64
") reached, refusing further inhibitors.", m
->inhibitors_max
);
2623 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2626 } while (hashmap_get(m
->inhibitors
, id
));
2628 r
= manager_add_inhibitor(m
, id
, &i
);
2636 i
->why
= strdup(why
);
2637 i
->who
= strdup(who
);
2639 if (!i
->why
|| !i
->who
) {
2644 fifo_fd
= inhibitor_create_fifo(i
);
2652 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2661 const sd_bus_vtable manager_vtable
[] = {
2662 SD_BUS_VTABLE_START(0),
2664 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2665 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2667 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2668 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2669 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2670 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2671 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2672 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2673 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2674 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2675 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2676 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2677 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2678 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2679 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2680 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2681 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2682 SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_ep
), SD_BUS_VTABLE_PROPERTY_CONST
),
2683 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2684 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2685 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2686 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2687 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2688 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2689 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2690 SD_BUS_PROPERTY("Docked", "b", property_get_docked
, 0, 0),
2691 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool
, offsetof(Manager
, remove_ipc
), SD_BUS_VTABLE_PROPERTY_CONST
),
2692 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size
, offsetof(Manager
, runtime_dir_size
), SD_BUS_VTABLE_PROPERTY_CONST
),
2693 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL
, offsetof(Manager
, inhibitors_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2694 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors
, 0, 0),
2695 SD_BUS_PROPERTY("SessionsMax", "t", NULL
, offsetof(Manager
, sessions_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2696 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions
, 0, 0),
2697 SD_BUS_PROPERTY("UserTasksMax", "t", NULL
, offsetof(Manager
, user_tasks_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2699 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2700 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2701 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2702 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2703 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2704 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2705 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2706 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2707 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2708 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2709 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2710 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2711 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2712 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2713 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2714 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2715 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2716 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2717 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2718 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2719 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2720 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2721 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2722 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2723 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2724 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2725 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2726 SD_BUS_METHOD("Halt", "b", NULL
, method_halt
, SD_BUS_VTABLE_UNPRIVILEGED
),
2727 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2728 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2729 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2730 SD_BUS_METHOD("SuspendThenHibernate", "b", NULL
, method_suspend_then_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2731 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2732 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2733 SD_BUS_METHOD("CanHalt", NULL
, "s", method_can_halt
, SD_BUS_VTABLE_UNPRIVILEGED
),
2734 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2735 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2736 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2737 SD_BUS_METHOD("CanSuspendThenHibernate", NULL
, "s", method_can_suspend_then_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2738 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2739 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2740 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2741 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2742 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2743 SD_BUS_METHOD("SetWallMessage", "sb", NULL
, method_set_wall_message
, SD_BUS_VTABLE_UNPRIVILEGED
),
2745 SD_BUS_SIGNAL("SessionNew", "so", 0),
2746 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2747 SD_BUS_SIGNAL("UserNew", "uo", 0),
2748 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2749 SD_BUS_SIGNAL("SeatNew", "so", 0),
2750 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2751 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2752 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2757 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2766 if (streq(result
, "done"))
2767 r
= session_send_create_reply(s
, NULL
);
2769 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
2771 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2772 r
= session_send_create_reply(s
, &e
);
2778 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2779 const char *path
, *result
, *unit
;
2780 Manager
*m
= userdata
;
2789 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2791 bus_log_parse_error(r
);
2795 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2796 log_info("Operation '%s' finished.", inhibit_what_to_string(m
->action_what
));
2798 /* Tell people that they now may take a lock again */
2799 (void) send_prepare_for(m
, m
->action_what
, false);
2801 m
->action_job
= mfree(m
->action_job
);
2802 m
->action_unit
= NULL
;
2807 session
= hashmap_get(m
->session_units
, unit
);
2808 if (session
&& streq_ptr(path
, session
->scope_job
)) {
2809 session
->scope_job
= mfree(session
->scope_job
);
2810 session_jobs_reply(session
, unit
, result
);
2812 session_save(session
);
2813 user_save(session
->user
);
2814 session_add_to_gc_queue(session
);
2817 user
= hashmap_get(m
->user_units
, unit
);
2819 (streq_ptr(path
, user
->service_job
) ||
2820 streq_ptr(path
, user
->slice_job
))) {
2822 if (streq_ptr(path
, user
->service_job
))
2823 user
->service_job
= mfree(user
->service_job
);
2825 if (streq_ptr(path
, user
->slice_job
))
2826 user
->slice_job
= mfree(user
->slice_job
);
2828 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
)
2829 session_jobs_reply(session
, unit
, result
);
2832 user_add_to_gc_queue(user
);
2838 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2839 const char *path
, *unit
;
2840 Manager
*m
= userdata
;
2848 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2850 bus_log_parse_error(r
);
2854 session
= hashmap_get(m
->session_units
, unit
);
2856 session_add_to_gc_queue(session
);
2858 user
= hashmap_get(m
->user_units
, unit
);
2860 user_add_to_gc_queue(user
);
2865 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2866 _cleanup_free_
char *unit
= NULL
;
2867 Manager
*m
= userdata
;
2876 path
= sd_bus_message_get_path(message
);
2880 r
= unit_name_from_dbus_path(path
, &unit
);
2881 if (r
== -EINVAL
) /* not a unit */
2888 session
= hashmap_get(m
->session_units
, unit
);
2890 session_add_to_gc_queue(session
);
2892 user
= hashmap_get(m
->user_units
, unit
);
2894 user_add_to_gc_queue(user
);
2899 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2900 Manager
*m
= userdata
;
2908 r
= sd_bus_message_read(message
, "b", &b
);
2910 bus_log_parse_error(r
);
2917 /* systemd finished reloading, let's recheck all our sessions */
2918 log_debug("System manager has been reloaded, rechecking sessions...");
2920 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2921 session_add_to_gc_queue(session
);
2926 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2931 l
= strv_from_stdarg_alloca(property
);
2933 return sd_bus_emit_properties_changed_strv(
2935 "/org/freedesktop/login1",
2936 "org.freedesktop.login1.Manager",
2940 static int strdup_job(sd_bus_message
*reply
, char **job
) {
2945 r
= sd_bus_message_read(reply
, "o", &j
);
2957 int manager_start_slice(
2960 const char *description
,
2964 sd_bus_error
*error
,
2967 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
2974 r
= sd_bus_message_new_method_call(
2977 "org.freedesktop.systemd1",
2978 "/org/freedesktop/systemd1",
2979 "org.freedesktop.systemd1.Manager",
2980 "StartTransientUnit");
2984 r
= sd_bus_message_append(m
, "ss", strempty(slice
), "fail");
2988 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2992 if (!isempty(description
)) {
2993 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2998 if (!isempty(after
)) {
2999 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
3004 if (!isempty(after2
)) {
3005 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
3010 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
3014 r
= sd_bus_message_close_container(m
);
3018 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
3022 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
3026 return strdup_job(reply
, job
);
3029 int manager_start_scope(
3034 const char *description
,
3038 sd_bus_error
*error
,
3041 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
3049 r
= sd_bus_message_new_method_call(
3052 "org.freedesktop.systemd1",
3053 "/org/freedesktop/systemd1",
3054 "org.freedesktop.systemd1.Manager",
3055 "StartTransientUnit");
3059 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
3063 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
3067 if (!isempty(slice
)) {
3068 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
3073 if (!isempty(description
)) {
3074 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
3079 if (!isempty(after
)) {
3080 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
3085 if (!isempty(after2
)) {
3086 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
3091 /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
3093 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
3097 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
3101 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
3105 r
= sd_bus_message_close_container(m
);
3109 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
3113 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
3117 return strdup_job(reply
, job
);
3120 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
3121 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3128 r
= sd_bus_call_method(
3130 "org.freedesktop.systemd1",
3131 "/org/freedesktop/systemd1",
3132 "org.freedesktop.systemd1.Manager",
3136 "ss", unit
, "replace");
3140 return strdup_job(reply
, job
);
3143 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
3144 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3151 r
= sd_bus_call_method(
3153 "org.freedesktop.systemd1",
3154 "/org/freedesktop/systemd1",
3155 "org.freedesktop.systemd1.Manager",
3159 "ss", unit
, "fail");
3161 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3162 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
3165 sd_bus_error_free(error
);
3172 return strdup_job(reply
, job
);
3175 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
3176 _cleanup_free_
char *path
= NULL
;
3182 path
= unit_dbus_path_from_name(scope
);
3186 r
= sd_bus_call_method(
3188 "org.freedesktop.systemd1",
3190 "org.freedesktop.systemd1.Scope",
3196 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3197 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
3198 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
3199 sd_bus_error_free(error
);
3209 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
3213 return sd_bus_call_method(
3215 "org.freedesktop.systemd1",
3216 "/org/freedesktop/systemd1",
3217 "org.freedesktop.systemd1.Manager",
3221 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
3224 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
3225 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3226 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3227 _cleanup_free_
char *path
= NULL
;
3234 path
= unit_dbus_path_from_name(unit
);
3238 r
= sd_bus_get_property(
3240 "org.freedesktop.systemd1",
3242 "org.freedesktop.systemd1.Unit",
3248 /* systemd might have droppped off momentarily, let's
3249 * not make this an error */
3250 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3251 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3254 /* If the unit is already unloaded then it's not
3256 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3257 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
3263 r
= sd_bus_message_read(reply
, "s", &state
);
3267 return !streq(state
, "inactive") && !streq(state
, "failed");
3270 int manager_job_is_active(Manager
*manager
, const char *path
) {
3271 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3272 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3278 r
= sd_bus_get_property(
3280 "org.freedesktop.systemd1",
3282 "org.freedesktop.systemd1.Job",
3288 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3289 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3292 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
3298 /* We don't actually care about the state really. The fact
3299 * that we could read the job state is enough for us */