1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "sd-messages.h"
30 #include "path-util.h"
32 #include "sleep-config.h"
33 #include "fileio-label.h"
34 #include "unit-name.h"
37 #include "bus-error.h"
38 #include "bus-common-errors.h"
39 #include "udev-util.h"
40 #include "selinux-util.h"
43 #include "formats-util.h"
44 #include "process-util.h"
45 #include "terminal-util.h"
46 #include "utmp-wtmp.h"
48 int manager_get_session_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Session
**ret
) {
49 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
58 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_AUGMENT
, &creds
);
62 r
= sd_bus_creds_get_session(creds
, &name
);
67 session
= hashmap_get(m
->sessions
, name
);
69 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SESSION
, "No session '%s' known", name
);
75 int manager_get_user_from_creds(Manager
*m
, sd_bus_message
*message
, uid_t uid
, sd_bus_error
*error
, User
**ret
) {
83 if (uid
== UID_INVALID
) {
84 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
86 /* Note that we get the owner UID of the session, not the actual client UID here! */
87 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
91 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
96 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
98 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER
, "No user "UID_FMT
" known or logged in", uid
);
104 int manager_get_seat_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Seat
**ret
) {
115 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
119 seat
= session
->seat
;
122 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "Session has no seat.");
124 seat
= hashmap_get(m
->seats
, name
);
126 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", name
);
133 static int property_get_idle_hint(
136 const char *interface
,
137 const char *property
,
138 sd_bus_message
*reply
,
140 sd_bus_error
*error
) {
142 Manager
*m
= userdata
;
148 return sd_bus_message_append(reply
, "b", manager_get_idle_hint(m
, NULL
) > 0);
151 static int property_get_idle_since_hint(
154 const char *interface
,
155 const char *property
,
156 sd_bus_message
*reply
,
158 sd_bus_error
*error
) {
160 Manager
*m
= userdata
;
161 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
167 manager_get_idle_hint(m
, &t
);
169 return sd_bus_message_append(reply
, "t", streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
);
172 static int property_get_inhibited(
175 const char *interface
,
176 const char *property
,
177 sd_bus_message
*reply
,
179 sd_bus_error
*error
) {
181 Manager
*m
= userdata
;
188 w
= manager_inhibit_what(m
, streq(property
, "BlockInhibited") ? INHIBIT_BLOCK
: INHIBIT_DELAY
);
190 return sd_bus_message_append(reply
, "s", inhibit_what_to_string(w
));
193 static int property_get_preparing(
196 const char *interface
,
197 const char *property
,
198 sd_bus_message
*reply
,
200 sd_bus_error
*error
) {
202 Manager
*m
= userdata
;
209 if (streq(property
, "PreparingForShutdown"))
210 b
= !!(m
->action_what
& INHIBIT_SHUTDOWN
);
212 b
= !!(m
->action_what
& INHIBIT_SLEEP
);
214 return sd_bus_message_append(reply
, "b", b
);
217 static int property_get_scheduled_shutdown(
220 const char *interface
,
221 const char *property
,
222 sd_bus_message
*reply
,
224 sd_bus_error
*error
) {
226 Manager
*m
= userdata
;
233 r
= sd_bus_message_open_container(reply
, 'r', "st");
237 r
= sd_bus_message_append(reply
, "st", m
->scheduled_shutdown_type
, m
->scheduled_shutdown_timeout
);
241 return sd_bus_message_close_container(reply
);
244 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action
, handle_action
, HandleAction
);
246 static int property_get_docked(
249 const char *interface
,
250 const char *property
,
251 sd_bus_message
*reply
,
253 sd_bus_error
*error
) {
255 Manager
*m
= userdata
;
261 return sd_bus_message_append(reply
, "b", manager_is_docked_or_external_displays(m
));
264 static int method_get_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
265 _cleanup_free_
char *p
= NULL
;
266 Manager
*m
= userdata
;
274 r
= sd_bus_message_read(message
, "s", &name
);
278 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
282 p
= session_bus_path(session
);
286 return sd_bus_reply_method_return(message
, "o", p
);
289 static int method_get_session_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
290 _cleanup_free_
char *p
= NULL
;
291 Session
*session
= NULL
;
292 Manager
*m
= userdata
;
299 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
301 r
= sd_bus_message_read(message
, "u", &pid
);
306 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
310 r
= manager_get_session_by_pid(m
, pid
, &session
);
315 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
318 p
= session_bus_path(session
);
322 return sd_bus_reply_method_return(message
, "o", p
);
325 static int method_get_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
326 _cleanup_free_
char *p
= NULL
;
327 Manager
*m
= userdata
;
335 r
= sd_bus_message_read(message
, "u", &uid
);
339 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
343 p
= user_bus_path(user
);
347 return sd_bus_reply_method_return(message
, "o", p
);
350 static int method_get_user_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
351 _cleanup_free_
char *p
= NULL
;
352 Manager
*m
= userdata
;
360 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
362 r
= sd_bus_message_read(message
, "u", &pid
);
367 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
371 r
= manager_get_user_by_pid(m
, pid
, &user
);
375 return sd_bus_error_setf(error
, BUS_ERROR_NO_USER_FOR_PID
, "PID "PID_FMT
" does not belong to any known or logged in user", pid
);
378 p
= user_bus_path(user
);
382 return sd_bus_reply_method_return(message
, "o", p
);
385 static int method_get_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
386 _cleanup_free_
char *p
= NULL
;
387 Manager
*m
= userdata
;
395 r
= sd_bus_message_read(message
, "s", &name
);
399 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
403 p
= seat_bus_path(seat
);
407 return sd_bus_reply_method_return(message
, "o", p
);
410 static int method_list_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
411 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
412 Manager
*m
= userdata
;
420 r
= sd_bus_message_new_method_return(message
, &reply
);
424 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
428 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
429 _cleanup_free_
char *p
= NULL
;
431 p
= session_bus_path(session
);
435 r
= sd_bus_message_append(reply
, "(susso)",
437 (uint32_t) session
->user
->uid
,
439 session
->seat
? session
->seat
->id
: "",
445 r
= sd_bus_message_close_container(reply
);
449 return sd_bus_send(NULL
, reply
, NULL
);
452 static int method_list_users(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
453 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
454 Manager
*m
= userdata
;
462 r
= sd_bus_message_new_method_return(message
, &reply
);
466 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
470 HASHMAP_FOREACH(user
, m
->users
, i
) {
471 _cleanup_free_
char *p
= NULL
;
473 p
= user_bus_path(user
);
477 r
= sd_bus_message_append(reply
, "(uso)",
478 (uint32_t) user
->uid
,
485 r
= sd_bus_message_close_container(reply
);
489 return sd_bus_send(NULL
, reply
, NULL
);
492 static int method_list_seats(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
493 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
494 Manager
*m
= userdata
;
502 r
= sd_bus_message_new_method_return(message
, &reply
);
506 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
510 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
511 _cleanup_free_
char *p
= NULL
;
513 p
= seat_bus_path(seat
);
517 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
522 r
= sd_bus_message_close_container(reply
);
526 return sd_bus_send(NULL
, reply
, NULL
);
529 static int method_list_inhibitors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
530 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
531 Manager
*m
= userdata
;
532 Inhibitor
*inhibitor
;
539 r
= sd_bus_message_new_method_return(message
, &reply
);
543 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
547 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
549 r
= sd_bus_message_append(reply
, "(ssssuu)",
550 strempty(inhibit_what_to_string(inhibitor
->what
)),
551 strempty(inhibitor
->who
),
552 strempty(inhibitor
->why
),
553 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
554 (uint32_t) inhibitor
->uid
,
555 (uint32_t) inhibitor
->pid
);
560 r
= sd_bus_message_close_container(reply
);
564 return sd_bus_send(NULL
, reply
, NULL
);
567 static int method_create_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
568 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
569 uint32_t uid
, leader
, audit_id
= 0;
570 _cleanup_free_
char *id
= NULL
;
571 Session
*session
= NULL
;
572 Manager
*m
= userdata
;
584 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
589 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
592 t
= _SESSION_TYPE_INVALID
;
594 t
= session_type_from_string(type
);
596 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
600 c
= _SESSION_CLASS_INVALID
;
602 c
= session_class_from_string(class);
604 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
607 if (isempty(desktop
))
610 if (!string_is_safe(desktop
))
611 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
617 seat
= hashmap_get(m
->seats
, cseat
);
619 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
622 if (tty_is_vc(tty
)) {
627 else if (seat
!= m
->seat0
)
628 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
);
630 v
= vtnr_from_tty(tty
);
632 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
636 else if (vtnr
!= (uint32_t) v
)
637 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
639 } else if (tty_is_console(tty
)) {
643 else if (seat
!= m
->seat0
)
644 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
647 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
651 if (seat_has_vts(seat
)) {
652 if (!vtnr
|| vtnr
> 63)
653 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
656 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
660 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
664 if (t
== _SESSION_TYPE_INVALID
) {
665 if (!isempty(display
))
667 else if (!isempty(tty
))
670 t
= SESSION_UNSPECIFIED
;
673 if (c
== _SESSION_CLASS_INVALID
) {
674 if (t
== SESSION_UNSPECIFIED
)
675 c
= SESSION_BACKGROUND
;
681 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
683 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
687 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
692 r
= manager_get_session_by_pid(m
, leader
, NULL
);
694 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already running in a session");
697 * Old gdm and lightdm start the user-session on the same VT as
698 * the greeter session. But they destroy the greeter session
699 * after the user-session and want the user-session to take
700 * over the VT. We need to support this for
701 * backwards-compatibility, so make sure we allow new sessions
702 * on a VT that a greeter is running on. Furthermore, to allow
703 * re-logins, we have to allow a greeter to take over a used VT for
704 * the exact same reasons.
706 if (c
!= SESSION_GREETER
&&
708 vtnr
< m
->seat0
->position_count
&&
709 m
->seat0
->positions
[vtnr
] &&
710 m
->seat0
->positions
[vtnr
]->class != SESSION_GREETER
)
711 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already occupied by a session");
713 audit_session_from_pid(leader
, &audit_id
);
715 /* Keep our session IDs and the audit session IDs in sync */
717 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
720 /* Wut? There's already a session by this name and we
721 * didn't find it above? Weird, then let's not trust
722 * the audit data and let's better register a new
724 if (hashmap_get(m
->sessions
, id
)) {
725 log_warning("Existing logind session ID %s used by new audit session, ignoring", id
);
736 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
739 } while (hashmap_get(m
->sessions
, id
));
742 r
= manager_add_user_by_uid(m
, uid
, &user
);
746 r
= manager_add_session(m
, id
, &session
);
750 session_set_user(session
, user
);
752 session
->leader
= leader
;
753 session
->audit_id
= audit_id
;
756 session
->remote
= remote
;
757 session
->vtnr
= vtnr
;
760 session
->tty
= strdup(tty
);
767 if (!isempty(display
)) {
768 session
->display
= strdup(display
);
769 if (!session
->display
) {
775 if (!isempty(remote_user
)) {
776 session
->remote_user
= strdup(remote_user
);
777 if (!session
->remote_user
) {
783 if (!isempty(remote_host
)) {
784 session
->remote_host
= strdup(remote_host
);
785 if (!session
->remote_host
) {
791 if (!isempty(service
)) {
792 session
->service
= strdup(service
);
793 if (!session
->service
) {
799 if (!isempty(desktop
)) {
800 session
->desktop
= strdup(desktop
);
801 if (!session
->desktop
) {
808 r
= seat_attach_session(seat
, session
);
813 r
= session_start(session
);
817 session
->create_message
= sd_bus_message_ref(message
);
819 /* Now, let's wait until the slice unit and stuff got
820 * created. We send the reply back from
821 * session_send_create_reply(). */
827 session_add_to_gc_queue(session
);
830 user_add_to_gc_queue(user
);
835 static int method_release_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
836 Manager
*m
= userdata
;
844 r
= sd_bus_message_read(message
, "s", &name
);
848 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
852 r
= session_release(session
);
856 return sd_bus_reply_method_return(message
, NULL
);
859 static int method_activate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
860 Manager
*m
= userdata
;
868 r
= sd_bus_message_read(message
, "s", &name
);
872 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
876 return bus_session_method_activate(message
, session
, error
);
879 static int method_activate_session_on_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
880 const char *session_name
, *seat_name
;
881 Manager
*m
= userdata
;
889 /* Same as ActivateSession() but refuses to work if
890 * the seat doesn't match */
892 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
896 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
900 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
904 if (session
->seat
!= seat
)
905 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
907 r
= session_activate(session
);
911 return sd_bus_reply_method_return(message
, NULL
);
914 static int method_lock_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
915 Manager
*m
= userdata
;
923 r
= sd_bus_message_read(message
, "s", &name
);
927 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
931 return bus_session_method_lock(message
, session
, error
);
934 static int method_lock_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
935 Manager
*m
= userdata
;
941 r
= bus_verify_polkit_async(
944 "org.freedesktop.login1.lock-sessions",
953 return 1; /* Will call us back */
955 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
959 return sd_bus_reply_method_return(message
, NULL
);
962 static int method_kill_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
964 Manager
*m
= userdata
;
971 r
= sd_bus_message_read(message
, "s", &name
);
975 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
979 return bus_session_method_kill(message
, session
, error
);
982 static int method_kill_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
983 Manager
*m
= userdata
;
991 r
= sd_bus_message_read(message
, "u", &uid
);
995 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
999 return bus_user_method_kill(message
, user
, error
);
1002 static int method_terminate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1003 Manager
*m
= userdata
;
1011 r
= sd_bus_message_read(message
, "s", &name
);
1015 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1019 return bus_session_method_terminate(message
, session
, error
);
1022 static int method_terminate_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1023 Manager
*m
= userdata
;
1031 r
= sd_bus_message_read(message
, "u", &uid
);
1035 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1039 return bus_user_method_terminate(message
, user
, error
);
1042 static int method_terminate_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1043 Manager
*m
= userdata
;
1051 r
= sd_bus_message_read(message
, "s", &name
);
1055 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
1059 return bus_seat_method_terminate(message
, seat
, error
);
1062 static int method_set_user_linger(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1063 _cleanup_free_
char *cc
= NULL
;
1064 Manager
*m
= userdata
;
1074 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1078 if (uid
== UID_INVALID
) {
1079 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1081 /* Note that we get the owner UID of the session, not the actual client UID here! */
1082 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1086 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1094 return errno
? -errno
: -ENOENT
;
1096 r
= bus_verify_polkit_async(
1099 "org.freedesktop.login1.set-user-linger",
1103 &m
->polkit_registry
,
1108 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1110 mkdir_p_label("/var/lib/systemd", 0755);
1112 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1116 cc
= cescape(pw
->pw_name
);
1120 path
= strjoina("/var/lib/systemd/linger/", cc
);
1128 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1135 if (r
< 0 && errno
!= ENOENT
)
1138 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1140 user_add_to_gc_queue(u
);
1143 return sd_bus_reply_method_return(message
, NULL
);
1146 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1147 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1148 struct udev_list_entry
*first
, *item
;
1153 e
= udev_enumerate_new(m
->udev
);
1158 r
= udev_enumerate_add_match_parent(e
, d
);
1163 r
= udev_enumerate_scan_devices(e
);
1167 first
= udev_enumerate_get_list_entry(e
);
1168 udev_list_entry_foreach(item
, first
) {
1169 _cleanup_free_
char *t
= NULL
;
1172 p
= udev_list_entry_get_name(item
);
1174 t
= strappend(p
, "/uevent");
1178 write_string_file(t
, "change", WRITE_STRING_FILE_CREATE
);
1184 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1185 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1186 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1187 const char *id_for_seat
;
1194 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1198 if (!udev_device_has_tag(d
, "seat"))
1201 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1205 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1208 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1211 mkdir_p_label("/etc/udev/rules.d", 0755);
1212 mac_selinux_init("/etc");
1213 r
= write_string_file_atomic_label(file
, rule
);
1217 return trigger_device(m
, d
);
1220 static int flush_devices(Manager
*m
) {
1221 _cleanup_closedir_
DIR *d
;
1225 d
= opendir("/etc/udev/rules.d");
1227 if (errno
!= ENOENT
)
1228 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1232 while ((de
= readdir(d
))) {
1234 if (!dirent_is_file(de
))
1237 if (!startswith(de
->d_name
, "72-seat-"))
1240 if (!endswith(de
->d_name
, ".rules"))
1243 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1244 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1248 return trigger_device(m
, NULL
);
1251 static int method_attach_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1252 const char *sysfs
, *seat
;
1253 Manager
*m
= userdata
;
1259 r
= sd_bus_message_read(message
, "ssb", &seat
, &sysfs
, &interactive
);
1263 if (!path_startswith(sysfs
, "/sys"))
1264 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not in /sys", sysfs
);
1266 if (!seat_name_is_valid(seat
))
1267 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat %s is not valid", seat
);
1269 r
= bus_verify_polkit_async(
1272 "org.freedesktop.login1.attach-device",
1276 &m
->polkit_registry
,
1281 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1283 r
= attach_device(m
, seat
, sysfs
);
1287 return sd_bus_reply_method_return(message
, NULL
);
1290 static int method_flush_devices(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1291 Manager
*m
= userdata
;
1297 r
= sd_bus_message_read(message
, "b", &interactive
);
1301 r
= bus_verify_polkit_async(
1304 "org.freedesktop.login1.flush-devices",
1308 &m
->polkit_registry
,
1313 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1315 r
= flush_devices(m
);
1319 return sd_bus_reply_method_return(message
, NULL
);
1322 static int have_multiple_sessions(
1331 /* Check for other users' sessions. Greeter sessions do not
1332 * count, and non-login sessions do not count either. */
1333 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1334 if (session
->class == SESSION_USER
&&
1335 session
->user
->uid
!= uid
)
1341 static int bus_manager_log_shutdown(
1344 const char *unit_name
) {
1351 if (w
!= INHIBIT_SHUTDOWN
)
1354 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1355 p
= "MESSAGE=System is powering down.";
1356 q
= "SHUTDOWN=power-off";
1357 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1358 p
= "MESSAGE=System is halting.";
1359 q
= "SHUTDOWN=halt";
1360 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1361 p
= "MESSAGE=System is rebooting.";
1362 q
= "SHUTDOWN=reboot";
1363 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1364 p
= "MESSAGE=System is rebooting with kexec.";
1365 q
= "SHUTDOWN=kexec";
1367 p
= "MESSAGE=System is shutting down.";
1371 if (!isempty(m
->wall_message
))
1372 p
= strjoina(p
, " (", m
->wall_message
, ")");
1374 return log_struct(LOG_NOTICE
,
1375 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN
),
1381 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1382 Manager
*m
= userdata
;
1387 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1391 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1396 if (until
<= now(CLOCK_MONOTONIC
))
1399 /* We want to ignore the lid switch for a while after each
1400 * suspend, and after boot-up. Hence let's install a timer for
1401 * this. As long as the event source exists we ignore the lid
1404 if (m
->lid_switch_ignore_event_source
) {
1407 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1414 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1416 r
= sd_event_add_time(
1418 &m
->lid_switch_ignore_event_source
,
1421 lid_switch_ignore_handler
, m
);
1426 static void reset_scheduled_shutdown(Manager
*m
) {
1427 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1428 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
1429 m
->nologin_timeout_source
= sd_event_source_unref(m
->nologin_timeout_source
);
1430 m
->scheduled_shutdown_type
= mfree(m
->scheduled_shutdown_type
);
1431 m
->scheduled_shutdown_timeout
= 0;
1432 m
->shutdown_dry_run
= false;
1434 if (m
->unlink_nologin
) {
1435 (void) unlink("/run/nologin");
1436 m
->unlink_nologin
= false;
1440 static int execute_shutdown_or_sleep(
1443 const char *unit_name
,
1444 sd_bus_error
*error
) {
1446 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1453 assert(w
< _INHIBIT_WHAT_MAX
);
1456 bus_manager_log_shutdown(m
, w
, unit_name
);
1458 if (m
->shutdown_dry_run
) {
1459 log_info("Running in dry run, suppressing action.");
1460 reset_scheduled_shutdown(m
);
1462 r
= sd_bus_call_method(
1464 "org.freedesktop.systemd1",
1465 "/org/freedesktop/systemd1",
1466 "org.freedesktop.systemd1.Manager",
1470 "ss", unit_name
, "replace-irreversibly");
1474 r
= sd_bus_message_read(reply
, "o", &p
);
1483 m
->action_unit
= unit_name
;
1484 free(m
->action_job
);
1488 /* Make sure the lid switch is ignored for a while */
1489 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1494 int manager_dispatch_delayed(Manager
*manager
, bool timeout
) {
1496 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1497 Inhibitor
*offending
= NULL
;
1502 if (manager
->action_what
== 0 || manager
->action_job
)
1505 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1506 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1511 (void) get_process_comm(offending
->pid
, &comm
);
1512 u
= uid_to_name(offending
->uid
);
1514 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1515 offending
->uid
, strna(u
),
1516 offending
->pid
, strna(comm
));
1519 /* Actually do the operation */
1520 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1522 log_warning("Failed to send delayed message: %s", bus_error_message(&error
, r
));
1524 manager
->action_unit
= NULL
;
1525 manager
->action_what
= 0;
1532 static int manager_inhibit_timeout_handler(
1537 Manager
*manager
= userdata
;
1541 assert(manager
->inhibit_timeout_source
== s
);
1543 r
= manager_dispatch_delayed(manager
, true);
1544 return (r
< 0) ? r
: 0;
1547 static int delay_shutdown_or_sleep(
1550 const char *unit_name
) {
1557 assert(w
< _INHIBIT_WHAT_MAX
);
1560 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1562 if (m
->inhibit_timeout_source
) {
1563 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1565 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1567 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1569 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1571 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1572 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1577 m
->action_unit
= unit_name
;
1583 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1585 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1586 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1587 [INHIBIT_SLEEP
] = "PrepareForSleep"
1590 int active
= _active
;
1594 assert(w
< _INHIBIT_WHAT_MAX
);
1595 assert(signal_name
[w
]);
1597 return sd_bus_emit_signal(m
->bus
,
1598 "/org/freedesktop/login1",
1599 "org.freedesktop.login1.Manager",
1605 int bus_manager_shutdown_or_sleep_now_or_later(
1607 const char *unit_name
,
1609 sd_bus_error
*error
) {
1617 assert(w
<= _INHIBIT_WHAT_MAX
);
1618 assert(!m
->action_job
);
1620 /* Tell everybody to prepare for shutdown/sleep */
1621 send_prepare_for(m
, w
, true);
1624 m
->inhibit_delay_max
> 0 &&
1625 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1628 /* Shutdown is delayed, keep in mind what we
1629 * want to do, and start a timeout */
1630 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1632 /* Shutdown is not delayed, execute it
1634 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1639 static int verify_shutdown_creds(
1641 sd_bus_message
*message
,
1645 const char *action_multiple_sessions
,
1646 const char *action_ignore_inhibit
,
1647 sd_bus_error
*error
) {
1649 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1650 bool multiple_sessions
, blocked
;
1657 assert(w
<= _INHIBIT_WHAT_MAX
);
1659 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1663 r
= sd_bus_creds_get_euid(creds
, &uid
);
1667 r
= have_multiple_sessions(m
, uid
);
1671 multiple_sessions
= r
> 0;
1672 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1674 if (multiple_sessions
&& action_multiple_sessions
) {
1675 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1679 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1682 if (blocked
&& action_ignore_inhibit
) {
1683 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1687 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1690 if (!multiple_sessions
&& !blocked
&& action
) {
1691 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1695 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1701 static int method_do_shutdown_or_sleep(
1703 sd_bus_message
*message
,
1704 const char *unit_name
,
1707 const char *action_multiple_sessions
,
1708 const char *action_ignore_inhibit
,
1709 const char *sleep_verb
,
1710 sd_bus_error
*error
) {
1718 assert(w
<= _INHIBIT_WHAT_MAX
);
1720 r
= sd_bus_message_read(message
, "b", &interactive
);
1724 /* Don't allow multiple jobs being executed at the same time */
1726 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1729 r
= can_sleep(sleep_verb
);
1734 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1737 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1738 action_ignore_inhibit
, error
);
1742 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1746 return sd_bus_reply_method_return(message
, NULL
);
1749 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1750 Manager
*m
= userdata
;
1752 return method_do_shutdown_or_sleep(
1754 SPECIAL_POWEROFF_TARGET
,
1756 "org.freedesktop.login1.power-off",
1757 "org.freedesktop.login1.power-off-multiple-sessions",
1758 "org.freedesktop.login1.power-off-ignore-inhibit",
1763 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1764 Manager
*m
= userdata
;
1766 return method_do_shutdown_or_sleep(
1768 SPECIAL_REBOOT_TARGET
,
1770 "org.freedesktop.login1.reboot",
1771 "org.freedesktop.login1.reboot-multiple-sessions",
1772 "org.freedesktop.login1.reboot-ignore-inhibit",
1777 static int method_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1778 Manager
*m
= userdata
;
1780 return method_do_shutdown_or_sleep(
1782 SPECIAL_SUSPEND_TARGET
,
1784 "org.freedesktop.login1.suspend",
1785 "org.freedesktop.login1.suspend-multiple-sessions",
1786 "org.freedesktop.login1.suspend-ignore-inhibit",
1791 static int nologin_timeout_handler(
1796 Manager
*m
= userdata
;
1799 log_info("Creating /run/nologin, blocking further logins...");
1801 r
= write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1803 log_error_errno(r
, "Failed to create /run/nologin: %m");
1805 m
->unlink_nologin
= true;
1810 static int update_schedule_file(Manager
*m
) {
1811 _cleanup_free_
char *temp_path
= NULL
;
1812 _cleanup_fclose_
FILE *f
= NULL
;
1817 r
= mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1819 return log_error_errno(r
, "Failed to create shutdown subdirectory: %m");
1821 r
= fopen_temporary("/run/systemd/shutdown/scheduled", &f
, &temp_path
);
1823 return log_error_errno(r
, "Failed to save information about scheduled shutdowns: %m");
1825 (void) fchmod(fileno(f
), 0644);
1831 m
->scheduled_shutdown_timeout
,
1832 m
->enable_wall_messages
,
1833 m
->scheduled_shutdown_type
);
1835 if (!isempty(m
->wall_message
)) {
1836 _cleanup_free_
char *t
;
1838 t
= cescape(m
->wall_message
);
1844 fprintf(f
, "WALL_MESSAGE=%s\n", t
);
1847 r
= fflush_and_check(f
);
1851 if (rename(temp_path
, "/run/systemd/shutdown/scheduled") < 0) {
1859 (void) unlink(temp_path
);
1860 (void) unlink("/run/systemd/shutdown/scheduled");
1862 return log_error_errno(r
, "Failed to write information about scheduled shutdowns: %m");
1865 static int manager_scheduled_shutdown_handler(
1870 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1871 Manager
*m
= userdata
;
1877 if (isempty(m
->scheduled_shutdown_type
))
1880 if (streq(m
->scheduled_shutdown_type
, "halt"))
1881 target
= SPECIAL_HALT_TARGET
;
1882 else if (streq(m
->scheduled_shutdown_type
, "poweroff"))
1883 target
= SPECIAL_POWEROFF_TARGET
;
1885 target
= SPECIAL_REBOOT_TARGET
;
1887 r
= execute_shutdown_or_sleep(m
, 0, target
, &error
);
1889 return log_error_errno(r
, "Unable to execute transition to %s: %m", target
);
1894 static int method_schedule_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1895 Manager
*m
= userdata
;
1896 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1897 const char *action_multiple_sessions
= NULL
;
1898 const char *action_ignore_inhibit
= NULL
;
1899 const char *action
= NULL
;
1907 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
1911 if (startswith(type
, "dry-")) {
1913 m
->shutdown_dry_run
= true;
1916 if (streq(type
, "reboot")) {
1917 action
= "org.freedesktop.login1.reboot";
1918 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
1919 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
1920 } else if (streq(type
, "halt")) {
1921 action
= "org.freedesktop.login1.halt";
1922 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
1923 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
1924 } else if (streq(type
, "poweroff")) {
1925 action
= "org.freedesktop.login1.poweroff";
1926 action_multiple_sessions
= "org.freedesktop.login1.poweroff-multiple-sessions";
1927 action_ignore_inhibit
= "org.freedesktop.login1.poweroff-ignore-inhibit";
1929 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
1931 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
1932 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
1936 if (m
->scheduled_shutdown_timeout_source
) {
1937 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
1939 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1941 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
1943 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1945 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
1946 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
1948 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1951 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
1953 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1957 if (m
->nologin_timeout_source
) {
1958 r
= sd_event_source_set_time(m
->nologin_timeout_source
, elapse
);
1960 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1962 r
= sd_event_source_set_enabled(m
->nologin_timeout_source
, SD_EVENT_ONESHOT
);
1964 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1966 r
= sd_event_add_time(m
->event
, &m
->nologin_timeout_source
,
1967 CLOCK_REALTIME
, elapse
- 5 * USEC_PER_MINUTE
, 0, nologin_timeout_handler
, m
);
1969 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1972 m
->scheduled_shutdown_timeout
= elapse
;
1974 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
1978 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
1979 (void) sd_bus_creds_get_tty(creds
, &tty
);
1981 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
1983 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1988 r
= manager_setup_wall_message_timer(m
);
1992 if (!isempty(type
)) {
1993 r
= update_schedule_file(m
);
1997 (void) unlink("/run/systemd/shutdown/scheduled");
1999 return sd_bus_reply_method_return(message
, NULL
);
2002 static int method_cancel_scheduled_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2003 Manager
*m
= userdata
;
2009 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
2010 reset_scheduled_shutdown(m
);
2013 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2014 const char *tty
= NULL
;
2018 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2020 (void) sd_bus_creds_get_uid(creds
, &uid
);
2021 (void) sd_bus_creds_get_tty(creds
, &tty
);
2024 utmp_wall("The system shutdown has been cancelled",
2025 lookup_uid(uid
), tty
, logind_wall_tty_filter
, m
);
2028 return sd_bus_reply_method_return(message
, "b", cancelled
);
2031 static int method_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2032 Manager
*m
= userdata
;
2034 return method_do_shutdown_or_sleep(
2036 SPECIAL_HIBERNATE_TARGET
,
2038 "org.freedesktop.login1.hibernate",
2039 "org.freedesktop.login1.hibernate-multiple-sessions",
2040 "org.freedesktop.login1.hibernate-ignore-inhibit",
2045 static int method_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2046 Manager
*m
= userdata
;
2048 return method_do_shutdown_or_sleep(
2050 SPECIAL_HYBRID_SLEEP_TARGET
,
2052 "org.freedesktop.login1.hibernate",
2053 "org.freedesktop.login1.hibernate-multiple-sessions",
2054 "org.freedesktop.login1.hibernate-ignore-inhibit",
2059 static int method_can_shutdown_or_sleep(
2061 sd_bus_message
*message
,
2064 const char *action_multiple_sessions
,
2065 const char *action_ignore_inhibit
,
2066 const char *sleep_verb
,
2067 sd_bus_error
*error
) {
2069 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2070 bool multiple_sessions
, challenge
, blocked
;
2071 const char *result
= NULL
;
2078 assert(w
<= _INHIBIT_WHAT_MAX
);
2080 assert(action_multiple_sessions
);
2081 assert(action_ignore_inhibit
);
2084 r
= can_sleep(sleep_verb
);
2088 return sd_bus_reply_method_return(message
, "s", "na");
2091 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
2095 r
= sd_bus_creds_get_euid(creds
, &uid
);
2099 r
= have_multiple_sessions(m
, uid
);
2103 multiple_sessions
= r
> 0;
2104 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
2106 if (multiple_sessions
) {
2107 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, UID_INVALID
, &challenge
, error
);
2114 result
= "challenge";
2120 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, UID_INVALID
, &challenge
, error
);
2124 if (r
> 0 && !result
)
2126 else if (challenge
&& (!result
|| streq(result
, "yes")))
2127 result
= "challenge";
2132 if (!multiple_sessions
&& !blocked
) {
2133 /* If neither inhibit nor multiple sessions
2134 * apply then just check the normal policy */
2136 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, NULL
, UID_INVALID
, &challenge
, error
);
2143 result
= "challenge";
2148 return sd_bus_reply_method_return(message
, "s", result
);
2151 static int method_can_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2152 Manager
*m
= userdata
;
2154 return method_can_shutdown_or_sleep(
2157 "org.freedesktop.login1.power-off",
2158 "org.freedesktop.login1.power-off-multiple-sessions",
2159 "org.freedesktop.login1.power-off-ignore-inhibit",
2164 static int method_can_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2165 Manager
*m
= userdata
;
2167 return method_can_shutdown_or_sleep(
2170 "org.freedesktop.login1.reboot",
2171 "org.freedesktop.login1.reboot-multiple-sessions",
2172 "org.freedesktop.login1.reboot-ignore-inhibit",
2177 static int method_can_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2178 Manager
*m
= userdata
;
2180 return method_can_shutdown_or_sleep(
2183 "org.freedesktop.login1.suspend",
2184 "org.freedesktop.login1.suspend-multiple-sessions",
2185 "org.freedesktop.login1.suspend-ignore-inhibit",
2190 static int method_can_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2191 Manager
*m
= userdata
;
2193 return method_can_shutdown_or_sleep(
2196 "org.freedesktop.login1.hibernate",
2197 "org.freedesktop.login1.hibernate-multiple-sessions",
2198 "org.freedesktop.login1.hibernate-ignore-inhibit",
2203 static int method_can_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2204 Manager
*m
= userdata
;
2206 return method_can_shutdown_or_sleep(
2209 "org.freedesktop.login1.hibernate",
2210 "org.freedesktop.login1.hibernate-multiple-sessions",
2211 "org.freedesktop.login1.hibernate-ignore-inhibit",
2216 static int property_get_reboot_to_firmware_setup(
2219 const char *interface
,
2220 const char *property
,
2221 sd_bus_message
*reply
,
2223 sd_bus_error
*error
) {
2230 r
= efi_get_reboot_to_firmware();
2231 if (r
< 0 && r
!= -EOPNOTSUPP
)
2234 return sd_bus_message_append(reply
, "b", r
> 0);
2237 static int method_set_reboot_to_firmware_setup(
2238 sd_bus_message
*message
,
2240 sd_bus_error
*error
) {
2243 Manager
*m
= userdata
;
2248 r
= sd_bus_message_read(message
, "b", &b
);
2252 r
= bus_verify_polkit_async(message
,
2254 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2258 &m
->polkit_registry
,
2263 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2265 r
= efi_set_reboot_to_firmware(b
);
2269 return sd_bus_reply_method_return(message
, NULL
);
2272 static int method_can_reboot_to_firmware_setup(
2273 sd_bus_message
*message
,
2275 sd_bus_error
*error
) {
2280 Manager
*m
= userdata
;
2285 r
= efi_reboot_to_firmware_supported();
2286 if (r
== -EOPNOTSUPP
)
2287 return sd_bus_reply_method_return(message
, "s", "na");
2291 r
= bus_test_polkit(message
,
2293 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2304 result
= "challenge";
2308 return sd_bus_reply_method_return(message
, "s", result
);
2311 static int method_set_wall_message(
2312 sd_bus_message
*message
,
2314 sd_bus_error
*error
) {
2317 Manager
*m
= userdata
;
2319 int enable_wall_messages
;
2324 r
= sd_bus_message_read(message
, "sb", &wall_message
, &enable_wall_messages
);
2328 r
= bus_verify_polkit_async(message
,
2330 "org.freedesktop.login1.set-wall-message",
2334 &m
->polkit_registry
,
2339 return 1; /* Will call us back */
2341 if (isempty(wall_message
))
2342 m
->wall_message
= mfree(m
->wall_message
);
2344 r
= free_and_strdup(&m
->wall_message
, wall_message
);
2349 m
->enable_wall_messages
= enable_wall_messages
;
2351 return sd_bus_reply_method_return(message
, NULL
);
2354 static int method_inhibit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2355 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2356 const char *who
, *why
, *what
, *mode
;
2357 _cleanup_free_
char *id
= NULL
;
2358 _cleanup_close_
int fifo_fd
= -1;
2359 Manager
*m
= userdata
;
2360 Inhibitor
*i
= NULL
;
2370 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2374 w
= inhibit_what_from_string(what
);
2376 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2378 mm
= inhibit_mode_from_string(mode
);
2380 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2382 /* Delay is only supported for shutdown/sleep */
2383 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2384 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2386 /* Don't allow taking delay locks while we are already
2387 * executing the operation. We shouldn't create the impression
2388 * that the lock was successful if the machine is about to go
2389 * down/suspend any moment. */
2390 if (m
->action_what
& w
)
2391 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2393 r
= bus_verify_polkit_async(
2396 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2397 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2398 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2399 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2400 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2401 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2402 "org.freedesktop.login1.inhibit-handle-lid-switch",
2406 &m
->polkit_registry
,
2411 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2413 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2417 r
= sd_bus_creds_get_euid(creds
, &uid
);
2421 r
= sd_bus_creds_get_pid(creds
, &pid
);
2428 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2431 } while (hashmap_get(m
->inhibitors
, id
));
2433 r
= manager_add_inhibitor(m
, id
, &i
);
2441 i
->why
= strdup(why
);
2442 i
->who
= strdup(who
);
2444 if (!i
->why
|| !i
->who
) {
2449 fifo_fd
= inhibitor_create_fifo(i
);
2457 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2466 const sd_bus_vtable manager_vtable
[] = {
2467 SD_BUS_VTABLE_START(0),
2469 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2470 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2472 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2473 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2474 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2475 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2476 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2477 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2478 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2479 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2480 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2481 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2482 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2483 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2484 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2485 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2486 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2487 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2488 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2489 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2490 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2491 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2492 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2493 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2494 SD_BUS_PROPERTY("Docked", "b", property_get_docked
, 0, 0),
2496 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2497 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2498 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2499 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2500 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2501 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2502 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2503 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2504 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2505 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2506 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2507 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2508 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2509 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2510 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2511 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2512 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2513 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2514 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2515 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2516 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2517 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2518 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2519 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2520 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2521 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2522 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2523 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2524 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2525 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2526 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2527 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2528 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2529 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2530 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2531 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2532 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2533 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2534 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2535 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2536 SD_BUS_METHOD("SetWallMessage", "sb", NULL
, method_set_wall_message
, SD_BUS_VTABLE_UNPRIVILEGED
),
2538 SD_BUS_SIGNAL("SessionNew", "so", 0),
2539 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2540 SD_BUS_SIGNAL("UserNew", "uo", 0),
2541 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2542 SD_BUS_SIGNAL("SeatNew", "so", 0),
2543 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2544 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2545 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2550 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2559 if (streq(result
, "done"))
2560 r
= session_send_create_reply(s
, NULL
);
2562 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
2564 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2565 r
= session_send_create_reply(s
, &e
);
2571 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2572 const char *path
, *result
, *unit
;
2573 Manager
*m
= userdata
;
2582 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2584 bus_log_parse_error(r
);
2588 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2589 log_info("Operation finished.");
2591 /* Tell people that they now may take a lock again */
2592 send_prepare_for(m
, m
->action_what
, false);
2594 m
->action_job
= mfree(m
->action_job
);
2595 m
->action_unit
= NULL
;
2600 session
= hashmap_get(m
->session_units
, unit
);
2603 if (streq_ptr(path
, session
->scope_job
))
2604 session
->scope_job
= mfree(session
->scope_job
);
2606 session_jobs_reply(session
, unit
, result
);
2608 session_save(session
);
2609 user_save(session
->user
);
2610 session_add_to_gc_queue(session
);
2613 user
= hashmap_get(m
->user_units
, unit
);
2616 if (streq_ptr(path
, user
->service_job
))
2617 user
->service_job
= mfree(user
->service_job
);
2619 if (streq_ptr(path
, user
->slice_job
))
2620 user
->slice_job
= mfree(user
->slice_job
);
2622 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
)
2623 session_jobs_reply(session
, unit
, result
);
2626 user_add_to_gc_queue(user
);
2632 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2633 const char *path
, *unit
;
2634 Manager
*m
= userdata
;
2642 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2644 bus_log_parse_error(r
);
2648 session
= hashmap_get(m
->session_units
, unit
);
2650 session_add_to_gc_queue(session
);
2652 user
= hashmap_get(m
->user_units
, unit
);
2654 user_add_to_gc_queue(user
);
2659 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2660 _cleanup_free_
char *unit
= NULL
;
2661 Manager
*m
= userdata
;
2670 path
= sd_bus_message_get_path(message
);
2674 r
= unit_name_from_dbus_path(path
, &unit
);
2675 if (r
== -EINVAL
) /* not a unit */
2682 session
= hashmap_get(m
->session_units
, unit
);
2684 session_add_to_gc_queue(session
);
2686 user
= hashmap_get(m
->user_units
, unit
);
2688 user_add_to_gc_queue(user
);
2693 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2694 Manager
*m
= userdata
;
2702 r
= sd_bus_message_read(message
, "b", &b
);
2704 bus_log_parse_error(r
);
2711 /* systemd finished reloading, let's recheck all our sessions */
2712 log_debug("System manager has been reloaded, rechecking sessions...");
2714 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2715 session_add_to_gc_queue(session
);
2720 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2725 l
= strv_from_stdarg_alloca(property
);
2727 return sd_bus_emit_properties_changed_strv(
2729 "/org/freedesktop/login1",
2730 "org.freedesktop.login1.Manager",
2734 int manager_start_scope(
2739 const char *description
,
2740 const char *after
, const char *after2
,
2741 sd_bus_error
*error
,
2744 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
2751 r
= sd_bus_message_new_method_call(
2754 "org.freedesktop.systemd1",
2755 "/org/freedesktop/systemd1",
2756 "org.freedesktop.systemd1.Manager",
2757 "StartTransientUnit");
2761 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
2765 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2769 if (!isempty(slice
)) {
2770 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
2775 if (!isempty(description
)) {
2776 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2781 if (!isempty(after
)) {
2782 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2787 if (!isempty(after2
)) {
2788 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2793 /* cgroup empty notification is not available in containers
2794 * currently. To make this less problematic, let's shorten the
2795 * stop timeout for sessions, so that we don't wait
2798 /* Make sure that the session shells are terminated with
2799 * SIGHUP since bash and friends tend to ignore SIGTERM */
2800 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
2804 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
2808 r
= sd_bus_message_close_container(m
);
2812 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2816 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2824 r
= sd_bus_message_read(reply
, "o", &j
);
2838 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2839 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2845 r
= sd_bus_call_method(
2847 "org.freedesktop.systemd1",
2848 "/org/freedesktop/systemd1",
2849 "org.freedesktop.systemd1.Manager",
2853 "ss", unit
, "fail");
2861 r
= sd_bus_message_read(reply
, "o", &j
);
2875 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2876 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2882 r
= sd_bus_call_method(
2884 "org.freedesktop.systemd1",
2885 "/org/freedesktop/systemd1",
2886 "org.freedesktop.systemd1.Manager",
2890 "ss", unit
, "fail");
2892 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2893 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
2898 sd_bus_error_free(error
);
2909 r
= sd_bus_message_read(reply
, "o", &j
);
2923 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
2924 _cleanup_free_
char *path
= NULL
;
2930 path
= unit_dbus_path_from_name(scope
);
2934 r
= sd_bus_call_method(
2936 "org.freedesktop.systemd1",
2938 "org.freedesktop.systemd1.Scope",
2944 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2945 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
2946 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
2947 sd_bus_error_free(error
);
2957 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
2961 return sd_bus_call_method(
2963 "org.freedesktop.systemd1",
2964 "/org/freedesktop/systemd1",
2965 "org.freedesktop.systemd1.Manager",
2969 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
2972 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
2973 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2974 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2975 _cleanup_free_
char *path
= NULL
;
2982 path
= unit_dbus_path_from_name(unit
);
2986 r
= sd_bus_get_property(
2988 "org.freedesktop.systemd1",
2990 "org.freedesktop.systemd1.Unit",
2996 /* systemd might have droppped off momentarily, let's
2997 * not make this an error */
2998 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
2999 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3002 /* If the unit is already unloaded then it's not
3004 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3005 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
3011 r
= sd_bus_message_read(reply
, "s", &state
);
3015 return !streq(state
, "inactive") && !streq(state
, "failed");
3018 int manager_job_is_active(Manager
*manager
, const char *path
) {
3019 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3020 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
3026 r
= sd_bus_get_property(
3028 "org.freedesktop.systemd1",
3030 "org.freedesktop.systemd1.Job",
3036 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3037 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3040 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
3046 /* We don't actually care about the state really. The fact
3047 * that we could read the job state is enough for us */