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 "bus-common-errors.h"
31 #include "bus-error.h"
33 #include "dirent-util.h"
37 #include "fileio-label.h"
38 #include "formats-util.h"
42 #include "path-util.h"
43 #include "process-util.h"
44 #include "selinux-util.h"
45 #include "sleep-config.h"
48 #include "terminal-util.h"
49 #include "udev-util.h"
50 #include "unit-name.h"
51 #include "user-util.h"
52 #include "utmp-wtmp.h"
54 int manager_get_session_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Session
**ret
) {
55 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
64 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_AUGMENT
, &creds
);
68 r
= sd_bus_creds_get_session(creds
, &name
);
73 session
= hashmap_get(m
->sessions
, name
);
75 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SESSION
, "No session '%s' known", name
);
81 int manager_get_user_from_creds(Manager
*m
, sd_bus_message
*message
, uid_t uid
, sd_bus_error
*error
, User
**ret
) {
89 if (uid
== UID_INVALID
) {
90 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
92 /* Note that we get the owner UID of the session, not the actual client UID here! */
93 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
97 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
102 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
104 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER
, "No user "UID_FMT
" known or logged in", uid
);
110 int manager_get_seat_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Seat
**ret
) {
121 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
125 seat
= session
->seat
;
128 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "Session has no seat.");
130 seat
= hashmap_get(m
->seats
, name
);
132 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", name
);
139 static int property_get_idle_hint(
142 const char *interface
,
143 const char *property
,
144 sd_bus_message
*reply
,
146 sd_bus_error
*error
) {
148 Manager
*m
= userdata
;
154 return sd_bus_message_append(reply
, "b", manager_get_idle_hint(m
, NULL
) > 0);
157 static int property_get_idle_since_hint(
160 const char *interface
,
161 const char *property
,
162 sd_bus_message
*reply
,
164 sd_bus_error
*error
) {
166 Manager
*m
= userdata
;
167 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
173 manager_get_idle_hint(m
, &t
);
175 return sd_bus_message_append(reply
, "t", streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
);
178 static int property_get_inhibited(
181 const char *interface
,
182 const char *property
,
183 sd_bus_message
*reply
,
185 sd_bus_error
*error
) {
187 Manager
*m
= userdata
;
194 w
= manager_inhibit_what(m
, streq(property
, "BlockInhibited") ? INHIBIT_BLOCK
: INHIBIT_DELAY
);
196 return sd_bus_message_append(reply
, "s", inhibit_what_to_string(w
));
199 static int property_get_preparing(
202 const char *interface
,
203 const char *property
,
204 sd_bus_message
*reply
,
206 sd_bus_error
*error
) {
208 Manager
*m
= userdata
;
215 if (streq(property
, "PreparingForShutdown"))
216 b
= !!(m
->action_what
& INHIBIT_SHUTDOWN
);
218 b
= !!(m
->action_what
& INHIBIT_SLEEP
);
220 return sd_bus_message_append(reply
, "b", b
);
223 static int property_get_scheduled_shutdown(
226 const char *interface
,
227 const char *property
,
228 sd_bus_message
*reply
,
230 sd_bus_error
*error
) {
232 Manager
*m
= userdata
;
239 r
= sd_bus_message_open_container(reply
, 'r', "st");
243 r
= sd_bus_message_append(reply
, "st", m
->scheduled_shutdown_type
, m
->scheduled_shutdown_timeout
);
247 return sd_bus_message_close_container(reply
);
250 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action
, handle_action
, HandleAction
);
252 static int property_get_docked(
255 const char *interface
,
256 const char *property
,
257 sd_bus_message
*reply
,
259 sd_bus_error
*error
) {
261 Manager
*m
= userdata
;
267 return sd_bus_message_append(reply
, "b", manager_is_docked_or_external_displays(m
));
270 static int method_get_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
271 _cleanup_free_
char *p
= NULL
;
272 Manager
*m
= userdata
;
280 r
= sd_bus_message_read(message
, "s", &name
);
284 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
288 p
= session_bus_path(session
);
292 return sd_bus_reply_method_return(message
, "o", p
);
295 static int method_get_session_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
296 _cleanup_free_
char *p
= NULL
;
297 Session
*session
= NULL
;
298 Manager
*m
= userdata
;
305 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
307 r
= sd_bus_message_read(message
, "u", &pid
);
312 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
316 r
= manager_get_session_by_pid(m
, pid
, &session
);
321 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
324 p
= session_bus_path(session
);
328 return sd_bus_reply_method_return(message
, "o", p
);
331 static int method_get_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
332 _cleanup_free_
char *p
= NULL
;
333 Manager
*m
= userdata
;
341 r
= sd_bus_message_read(message
, "u", &uid
);
345 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
349 p
= user_bus_path(user
);
353 return sd_bus_reply_method_return(message
, "o", p
);
356 static int method_get_user_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
357 _cleanup_free_
char *p
= NULL
;
358 Manager
*m
= userdata
;
366 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
368 r
= sd_bus_message_read(message
, "u", &pid
);
373 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
377 r
= manager_get_user_by_pid(m
, pid
, &user
);
381 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
);
384 p
= user_bus_path(user
);
388 return sd_bus_reply_method_return(message
, "o", p
);
391 static int method_get_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
392 _cleanup_free_
char *p
= NULL
;
393 Manager
*m
= userdata
;
401 r
= sd_bus_message_read(message
, "s", &name
);
405 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
409 p
= seat_bus_path(seat
);
413 return sd_bus_reply_method_return(message
, "o", p
);
416 static int method_list_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
417 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
418 Manager
*m
= userdata
;
426 r
= sd_bus_message_new_method_return(message
, &reply
);
430 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
434 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
435 _cleanup_free_
char *p
= NULL
;
437 p
= session_bus_path(session
);
441 r
= sd_bus_message_append(reply
, "(susso)",
443 (uint32_t) session
->user
->uid
,
445 session
->seat
? session
->seat
->id
: "",
451 r
= sd_bus_message_close_container(reply
);
455 return sd_bus_send(NULL
, reply
, NULL
);
458 static int method_list_users(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
459 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
460 Manager
*m
= userdata
;
468 r
= sd_bus_message_new_method_return(message
, &reply
);
472 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
476 HASHMAP_FOREACH(user
, m
->users
, i
) {
477 _cleanup_free_
char *p
= NULL
;
479 p
= user_bus_path(user
);
483 r
= sd_bus_message_append(reply
, "(uso)",
484 (uint32_t) user
->uid
,
491 r
= sd_bus_message_close_container(reply
);
495 return sd_bus_send(NULL
, reply
, NULL
);
498 static int method_list_seats(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
499 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
500 Manager
*m
= userdata
;
508 r
= sd_bus_message_new_method_return(message
, &reply
);
512 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
516 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
517 _cleanup_free_
char *p
= NULL
;
519 p
= seat_bus_path(seat
);
523 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
528 r
= sd_bus_message_close_container(reply
);
532 return sd_bus_send(NULL
, reply
, NULL
);
535 static int method_list_inhibitors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
536 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
537 Manager
*m
= userdata
;
538 Inhibitor
*inhibitor
;
545 r
= sd_bus_message_new_method_return(message
, &reply
);
549 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
553 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
555 r
= sd_bus_message_append(reply
, "(ssssuu)",
556 strempty(inhibit_what_to_string(inhibitor
->what
)),
557 strempty(inhibitor
->who
),
558 strempty(inhibitor
->why
),
559 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
560 (uint32_t) inhibitor
->uid
,
561 (uint32_t) inhibitor
->pid
);
566 r
= sd_bus_message_close_container(reply
);
570 return sd_bus_send(NULL
, reply
, NULL
);
573 static int method_create_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
574 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
575 uint32_t uid
, leader
, audit_id
= 0;
576 _cleanup_free_
char *id
= NULL
;
577 Session
*session
= NULL
;
578 Manager
*m
= userdata
;
590 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
595 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
598 t
= _SESSION_TYPE_INVALID
;
600 t
= session_type_from_string(type
);
602 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
606 c
= _SESSION_CLASS_INVALID
;
608 c
= session_class_from_string(class);
610 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
613 if (isempty(desktop
))
616 if (!string_is_safe(desktop
))
617 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
623 seat
= hashmap_get(m
->seats
, cseat
);
625 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
628 if (tty_is_vc(tty
)) {
633 else if (seat
!= m
->seat0
)
634 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
);
636 v
= vtnr_from_tty(tty
);
638 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
642 else if (vtnr
!= (uint32_t) v
)
643 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
645 } else if (tty_is_console(tty
)) {
649 else if (seat
!= m
->seat0
)
650 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
653 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
657 if (seat_has_vts(seat
)) {
658 if (!vtnr
|| vtnr
> 63)
659 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
662 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
666 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
670 if (t
== _SESSION_TYPE_INVALID
) {
671 if (!isempty(display
))
673 else if (!isempty(tty
))
676 t
= SESSION_UNSPECIFIED
;
679 if (c
== _SESSION_CLASS_INVALID
) {
680 if (t
== SESSION_UNSPECIFIED
)
681 c
= SESSION_BACKGROUND
;
687 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
689 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
693 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
698 r
= manager_get_session_by_pid(m
, leader
, NULL
);
700 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already running in a session");
703 * Old gdm and lightdm start the user-session on the same VT as
704 * the greeter session. But they destroy the greeter session
705 * after the user-session and want the user-session to take
706 * over the VT. We need to support this for
707 * backwards-compatibility, so make sure we allow new sessions
708 * on a VT that a greeter is running on. Furthermore, to allow
709 * re-logins, we have to allow a greeter to take over a used VT for
710 * the exact same reasons.
712 if (c
!= SESSION_GREETER
&&
714 vtnr
< m
->seat0
->position_count
&&
715 m
->seat0
->positions
[vtnr
] &&
716 m
->seat0
->positions
[vtnr
]->class != SESSION_GREETER
)
717 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already occupied by a session");
719 audit_session_from_pid(leader
, &audit_id
);
721 /* Keep our session IDs and the audit session IDs in sync */
723 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
726 /* Wut? There's already a session by this name and we
727 * didn't find it above? Weird, then let's not trust
728 * the audit data and let's better register a new
730 if (hashmap_get(m
->sessions
, id
)) {
731 log_warning("Existing logind session ID %s used by new audit session, ignoring", id
);
742 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
745 } while (hashmap_get(m
->sessions
, id
));
748 r
= manager_add_user_by_uid(m
, uid
, &user
);
752 r
= manager_add_session(m
, id
, &session
);
756 session_set_user(session
, user
);
758 session
->leader
= leader
;
759 session
->audit_id
= audit_id
;
762 session
->remote
= remote
;
763 session
->vtnr
= vtnr
;
766 session
->tty
= strdup(tty
);
773 if (!isempty(display
)) {
774 session
->display
= strdup(display
);
775 if (!session
->display
) {
781 if (!isempty(remote_user
)) {
782 session
->remote_user
= strdup(remote_user
);
783 if (!session
->remote_user
) {
789 if (!isempty(remote_host
)) {
790 session
->remote_host
= strdup(remote_host
);
791 if (!session
->remote_host
) {
797 if (!isempty(service
)) {
798 session
->service
= strdup(service
);
799 if (!session
->service
) {
805 if (!isempty(desktop
)) {
806 session
->desktop
= strdup(desktop
);
807 if (!session
->desktop
) {
814 r
= seat_attach_session(seat
, session
);
819 r
= session_start(session
);
823 session
->create_message
= sd_bus_message_ref(message
);
825 /* Now, let's wait until the slice unit and stuff got
826 * created. We send the reply back from
827 * session_send_create_reply(). */
833 session_add_to_gc_queue(session
);
836 user_add_to_gc_queue(user
);
841 static int method_release_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
842 Manager
*m
= userdata
;
850 r
= sd_bus_message_read(message
, "s", &name
);
854 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
858 r
= session_release(session
);
862 return sd_bus_reply_method_return(message
, NULL
);
865 static int method_activate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
866 Manager
*m
= userdata
;
874 r
= sd_bus_message_read(message
, "s", &name
);
878 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
882 return bus_session_method_activate(message
, session
, error
);
885 static int method_activate_session_on_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
886 const char *session_name
, *seat_name
;
887 Manager
*m
= userdata
;
895 /* Same as ActivateSession() but refuses to work if
896 * the seat doesn't match */
898 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
902 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
906 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
910 if (session
->seat
!= seat
)
911 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
913 r
= session_activate(session
);
917 return sd_bus_reply_method_return(message
, NULL
);
920 static int method_lock_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
921 Manager
*m
= userdata
;
929 r
= sd_bus_message_read(message
, "s", &name
);
933 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
937 return bus_session_method_lock(message
, session
, error
);
940 static int method_lock_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
941 Manager
*m
= userdata
;
947 r
= bus_verify_polkit_async(
950 "org.freedesktop.login1.lock-sessions",
959 return 1; /* Will call us back */
961 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
965 return sd_bus_reply_method_return(message
, NULL
);
968 static int method_kill_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
970 Manager
*m
= userdata
;
977 r
= sd_bus_message_read(message
, "s", &name
);
981 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
985 return bus_session_method_kill(message
, session
, error
);
988 static int method_kill_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
989 Manager
*m
= userdata
;
997 r
= sd_bus_message_read(message
, "u", &uid
);
1001 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1005 return bus_user_method_kill(message
, user
, error
);
1008 static int method_terminate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1009 Manager
*m
= userdata
;
1017 r
= sd_bus_message_read(message
, "s", &name
);
1021 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1025 return bus_session_method_terminate(message
, session
, error
);
1028 static int method_terminate_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1029 Manager
*m
= userdata
;
1037 r
= sd_bus_message_read(message
, "u", &uid
);
1041 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1045 return bus_user_method_terminate(message
, user
, error
);
1048 static int method_terminate_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1049 Manager
*m
= userdata
;
1057 r
= sd_bus_message_read(message
, "s", &name
);
1061 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
1065 return bus_seat_method_terminate(message
, seat
, error
);
1068 static int method_set_user_linger(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1069 _cleanup_free_
char *cc
= NULL
;
1070 Manager
*m
= userdata
;
1080 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1084 if (uid
== UID_INVALID
) {
1085 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1087 /* Note that we get the owner UID of the session, not the actual client UID here! */
1088 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1092 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1100 return errno
? -errno
: -ENOENT
;
1102 r
= bus_verify_polkit_async(
1105 "org.freedesktop.login1.set-user-linger",
1109 &m
->polkit_registry
,
1114 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1116 mkdir_p_label("/var/lib/systemd", 0755);
1118 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1122 cc
= cescape(pw
->pw_name
);
1126 path
= strjoina("/var/lib/systemd/linger/", cc
);
1134 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1141 if (r
< 0 && errno
!= ENOENT
)
1144 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1146 user_add_to_gc_queue(u
);
1149 return sd_bus_reply_method_return(message
, NULL
);
1152 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1153 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1154 struct udev_list_entry
*first
, *item
;
1159 e
= udev_enumerate_new(m
->udev
);
1164 r
= udev_enumerate_add_match_parent(e
, d
);
1169 r
= udev_enumerate_scan_devices(e
);
1173 first
= udev_enumerate_get_list_entry(e
);
1174 udev_list_entry_foreach(item
, first
) {
1175 _cleanup_free_
char *t
= NULL
;
1178 p
= udev_list_entry_get_name(item
);
1180 t
= strappend(p
, "/uevent");
1184 write_string_file(t
, "change", WRITE_STRING_FILE_CREATE
);
1190 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1191 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1192 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1193 const char *id_for_seat
;
1200 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1204 if (!udev_device_has_tag(d
, "seat"))
1207 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1211 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1214 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1217 mkdir_p_label("/etc/udev/rules.d", 0755);
1218 mac_selinux_init("/etc");
1219 r
= write_string_file_atomic_label(file
, rule
);
1223 return trigger_device(m
, d
);
1226 static int flush_devices(Manager
*m
) {
1227 _cleanup_closedir_
DIR *d
;
1231 d
= opendir("/etc/udev/rules.d");
1233 if (errno
!= ENOENT
)
1234 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1238 while ((de
= readdir(d
))) {
1240 if (!dirent_is_file(de
))
1243 if (!startswith(de
->d_name
, "72-seat-"))
1246 if (!endswith(de
->d_name
, ".rules"))
1249 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1250 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1254 return trigger_device(m
, NULL
);
1257 static int method_attach_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1258 const char *sysfs
, *seat
;
1259 Manager
*m
= userdata
;
1265 r
= sd_bus_message_read(message
, "ssb", &seat
, &sysfs
, &interactive
);
1269 if (!path_startswith(sysfs
, "/sys"))
1270 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not in /sys", sysfs
);
1272 if (!seat_name_is_valid(seat
))
1273 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat %s is not valid", seat
);
1275 r
= bus_verify_polkit_async(
1278 "org.freedesktop.login1.attach-device",
1282 &m
->polkit_registry
,
1287 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1289 r
= attach_device(m
, seat
, sysfs
);
1293 return sd_bus_reply_method_return(message
, NULL
);
1296 static int method_flush_devices(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1297 Manager
*m
= userdata
;
1303 r
= sd_bus_message_read(message
, "b", &interactive
);
1307 r
= bus_verify_polkit_async(
1310 "org.freedesktop.login1.flush-devices",
1314 &m
->polkit_registry
,
1319 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1321 r
= flush_devices(m
);
1325 return sd_bus_reply_method_return(message
, NULL
);
1328 static int have_multiple_sessions(
1337 /* Check for other users' sessions. Greeter sessions do not
1338 * count, and non-login sessions do not count either. */
1339 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1340 if (session
->class == SESSION_USER
&&
1341 session
->user
->uid
!= uid
)
1347 static int bus_manager_log_shutdown(
1350 const char *unit_name
) {
1357 if (w
!= INHIBIT_SHUTDOWN
)
1360 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1361 p
= "MESSAGE=System is powering down";
1362 q
= "SHUTDOWN=power-off";
1363 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1364 p
= "MESSAGE=System is halting";
1365 q
= "SHUTDOWN=halt";
1366 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1367 p
= "MESSAGE=System is rebooting";
1368 q
= "SHUTDOWN=reboot";
1369 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1370 p
= "MESSAGE=System is rebooting with kexec";
1371 q
= "SHUTDOWN=kexec";
1373 p
= "MESSAGE=System is shutting down";
1377 if (isempty(m
->wall_message
))
1378 p
= strjoina(p
, ".");
1380 p
= strjoina(p
, " (", m
->wall_message
, ").");
1382 return log_struct(LOG_NOTICE
,
1383 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN
),
1389 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1390 Manager
*m
= userdata
;
1395 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1399 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1404 if (until
<= now(CLOCK_MONOTONIC
))
1407 /* We want to ignore the lid switch for a while after each
1408 * suspend, and after boot-up. Hence let's install a timer for
1409 * this. As long as the event source exists we ignore the lid
1412 if (m
->lid_switch_ignore_event_source
) {
1415 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1422 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1424 r
= sd_event_add_time(
1426 &m
->lid_switch_ignore_event_source
,
1429 lid_switch_ignore_handler
, m
);
1434 static void reset_scheduled_shutdown(Manager
*m
) {
1435 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1436 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
1437 m
->nologin_timeout_source
= sd_event_source_unref(m
->nologin_timeout_source
);
1438 m
->scheduled_shutdown_type
= mfree(m
->scheduled_shutdown_type
);
1439 m
->scheduled_shutdown_timeout
= 0;
1440 m
->shutdown_dry_run
= false;
1442 if (m
->unlink_nologin
) {
1443 (void) unlink("/run/nologin");
1444 m
->unlink_nologin
= false;
1448 static int execute_shutdown_or_sleep(
1451 const char *unit_name
,
1452 sd_bus_error
*error
) {
1454 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1461 assert(w
< _INHIBIT_WHAT_MAX
);
1464 bus_manager_log_shutdown(m
, w
, unit_name
);
1466 if (m
->shutdown_dry_run
) {
1467 log_info("Running in dry run, suppressing action.");
1468 reset_scheduled_shutdown(m
);
1470 r
= sd_bus_call_method(
1472 "org.freedesktop.systemd1",
1473 "/org/freedesktop/systemd1",
1474 "org.freedesktop.systemd1.Manager",
1478 "ss", unit_name
, "replace-irreversibly");
1482 r
= sd_bus_message_read(reply
, "o", &p
);
1491 m
->action_unit
= unit_name
;
1492 free(m
->action_job
);
1496 /* Make sure the lid switch is ignored for a while */
1497 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1502 int manager_dispatch_delayed(Manager
*manager
, bool timeout
) {
1504 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1505 Inhibitor
*offending
= NULL
;
1510 if (manager
->action_what
== 0 || manager
->action_job
)
1513 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1514 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1519 (void) get_process_comm(offending
->pid
, &comm
);
1520 u
= uid_to_name(offending
->uid
);
1522 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1523 offending
->uid
, strna(u
),
1524 offending
->pid
, strna(comm
));
1527 /* Actually do the operation */
1528 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1530 log_warning("Failed to send delayed message: %s", bus_error_message(&error
, r
));
1532 manager
->action_unit
= NULL
;
1533 manager
->action_what
= 0;
1540 static int manager_inhibit_timeout_handler(
1545 Manager
*manager
= userdata
;
1549 assert(manager
->inhibit_timeout_source
== s
);
1551 r
= manager_dispatch_delayed(manager
, true);
1552 return (r
< 0) ? r
: 0;
1555 static int delay_shutdown_or_sleep(
1558 const char *unit_name
) {
1565 assert(w
< _INHIBIT_WHAT_MAX
);
1568 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1570 if (m
->inhibit_timeout_source
) {
1571 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1573 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1575 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1577 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1579 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1580 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1585 m
->action_unit
= unit_name
;
1591 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1593 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1594 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1595 [INHIBIT_SLEEP
] = "PrepareForSleep"
1598 int active
= _active
;
1602 assert(w
< _INHIBIT_WHAT_MAX
);
1603 assert(signal_name
[w
]);
1605 return sd_bus_emit_signal(m
->bus
,
1606 "/org/freedesktop/login1",
1607 "org.freedesktop.login1.Manager",
1613 int bus_manager_shutdown_or_sleep_now_or_later(
1615 const char *unit_name
,
1617 sd_bus_error
*error
) {
1625 assert(w
<= _INHIBIT_WHAT_MAX
);
1626 assert(!m
->action_job
);
1628 /* Tell everybody to prepare for shutdown/sleep */
1629 send_prepare_for(m
, w
, true);
1632 m
->inhibit_delay_max
> 0 &&
1633 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1636 /* Shutdown is delayed, keep in mind what we
1637 * want to do, and start a timeout */
1638 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1640 /* Shutdown is not delayed, execute it
1642 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1647 static int verify_shutdown_creds(
1649 sd_bus_message
*message
,
1653 const char *action_multiple_sessions
,
1654 const char *action_ignore_inhibit
,
1655 sd_bus_error
*error
) {
1657 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1658 bool multiple_sessions
, blocked
;
1665 assert(w
<= _INHIBIT_WHAT_MAX
);
1667 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1671 r
= sd_bus_creds_get_euid(creds
, &uid
);
1675 r
= have_multiple_sessions(m
, uid
);
1679 multiple_sessions
= r
> 0;
1680 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1682 if (multiple_sessions
&& action_multiple_sessions
) {
1683 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, 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 (blocked
&& action_ignore_inhibit
) {
1691 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, 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 */
1698 if (!multiple_sessions
&& !blocked
&& action
) {
1699 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1703 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1709 static int method_do_shutdown_or_sleep(
1711 sd_bus_message
*message
,
1712 const char *unit_name
,
1715 const char *action_multiple_sessions
,
1716 const char *action_ignore_inhibit
,
1717 const char *sleep_verb
,
1718 sd_bus_error
*error
) {
1726 assert(w
<= _INHIBIT_WHAT_MAX
);
1728 r
= sd_bus_message_read(message
, "b", &interactive
);
1732 /* Don't allow multiple jobs being executed at the same time */
1734 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1737 r
= can_sleep(sleep_verb
);
1742 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1745 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1746 action_ignore_inhibit
, error
);
1750 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1754 return sd_bus_reply_method_return(message
, NULL
);
1757 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1758 Manager
*m
= userdata
;
1760 return method_do_shutdown_or_sleep(
1762 SPECIAL_POWEROFF_TARGET
,
1764 "org.freedesktop.login1.power-off",
1765 "org.freedesktop.login1.power-off-multiple-sessions",
1766 "org.freedesktop.login1.power-off-ignore-inhibit",
1771 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1772 Manager
*m
= userdata
;
1774 return method_do_shutdown_or_sleep(
1776 SPECIAL_REBOOT_TARGET
,
1778 "org.freedesktop.login1.reboot",
1779 "org.freedesktop.login1.reboot-multiple-sessions",
1780 "org.freedesktop.login1.reboot-ignore-inhibit",
1785 static int method_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1786 Manager
*m
= userdata
;
1788 return method_do_shutdown_or_sleep(
1790 SPECIAL_SUSPEND_TARGET
,
1792 "org.freedesktop.login1.suspend",
1793 "org.freedesktop.login1.suspend-multiple-sessions",
1794 "org.freedesktop.login1.suspend-ignore-inhibit",
1799 static int nologin_timeout_handler(
1804 Manager
*m
= userdata
;
1807 log_info("Creating /run/nologin, blocking further logins...");
1809 r
= write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1811 log_error_errno(r
, "Failed to create /run/nologin: %m");
1813 m
->unlink_nologin
= true;
1818 static int update_schedule_file(Manager
*m
) {
1819 _cleanup_free_
char *temp_path
= NULL
;
1820 _cleanup_fclose_
FILE *f
= NULL
;
1825 r
= mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1827 return log_error_errno(r
, "Failed to create shutdown subdirectory: %m");
1829 r
= fopen_temporary("/run/systemd/shutdown/scheduled", &f
, &temp_path
);
1831 return log_error_errno(r
, "Failed to save information about scheduled shutdowns: %m");
1833 (void) fchmod(fileno(f
), 0644);
1839 m
->scheduled_shutdown_timeout
,
1840 m
->enable_wall_messages
,
1841 m
->scheduled_shutdown_type
);
1843 if (!isempty(m
->wall_message
)) {
1844 _cleanup_free_
char *t
;
1846 t
= cescape(m
->wall_message
);
1852 fprintf(f
, "WALL_MESSAGE=%s\n", t
);
1855 r
= fflush_and_check(f
);
1859 if (rename(temp_path
, "/run/systemd/shutdown/scheduled") < 0) {
1867 (void) unlink(temp_path
);
1868 (void) unlink("/run/systemd/shutdown/scheduled");
1870 return log_error_errno(r
, "Failed to write information about scheduled shutdowns: %m");
1873 static int manager_scheduled_shutdown_handler(
1878 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1879 Manager
*m
= userdata
;
1885 if (isempty(m
->scheduled_shutdown_type
))
1888 if (streq(m
->scheduled_shutdown_type
, "halt"))
1889 target
= SPECIAL_HALT_TARGET
;
1890 else if (streq(m
->scheduled_shutdown_type
, "poweroff"))
1891 target
= SPECIAL_POWEROFF_TARGET
;
1893 target
= SPECIAL_REBOOT_TARGET
;
1895 r
= execute_shutdown_or_sleep(m
, 0, target
, &error
);
1897 return log_error_errno(r
, "Unable to execute transition to %s: %m", target
);
1902 static int method_schedule_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1903 Manager
*m
= userdata
;
1904 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1905 const char *action_multiple_sessions
= NULL
;
1906 const char *action_ignore_inhibit
= NULL
;
1907 const char *action
= NULL
;
1915 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
1919 if (startswith(type
, "dry-")) {
1921 m
->shutdown_dry_run
= true;
1924 if (streq(type
, "reboot")) {
1925 action
= "org.freedesktop.login1.reboot";
1926 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
1927 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
1928 } else if (streq(type
, "halt")) {
1929 action
= "org.freedesktop.login1.halt";
1930 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
1931 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
1932 } else if (streq(type
, "poweroff")) {
1933 action
= "org.freedesktop.login1.poweroff";
1934 action_multiple_sessions
= "org.freedesktop.login1.poweroff-multiple-sessions";
1935 action_ignore_inhibit
= "org.freedesktop.login1.poweroff-ignore-inhibit";
1937 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
1939 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
1940 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
1944 if (m
->scheduled_shutdown_timeout_source
) {
1945 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
1947 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1949 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
1951 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1953 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
1954 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
1956 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1959 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
1961 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1965 if (m
->nologin_timeout_source
) {
1966 r
= sd_event_source_set_time(m
->nologin_timeout_source
, elapse
);
1968 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1970 r
= sd_event_source_set_enabled(m
->nologin_timeout_source
, SD_EVENT_ONESHOT
);
1972 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1974 r
= sd_event_add_time(m
->event
, &m
->nologin_timeout_source
,
1975 CLOCK_REALTIME
, elapse
- 5 * USEC_PER_MINUTE
, 0, nologin_timeout_handler
, m
);
1977 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1980 m
->scheduled_shutdown_timeout
= elapse
;
1982 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
1986 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
1987 (void) sd_bus_creds_get_tty(creds
, &tty
);
1989 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
1991 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1996 r
= manager_setup_wall_message_timer(m
);
2000 if (!isempty(type
)) {
2001 r
= update_schedule_file(m
);
2005 (void) unlink("/run/systemd/shutdown/scheduled");
2007 return sd_bus_reply_method_return(message
, NULL
);
2010 static int method_cancel_scheduled_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2011 Manager
*m
= userdata
;
2017 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
2018 reset_scheduled_shutdown(m
);
2021 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2022 const char *tty
= NULL
;
2026 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2028 (void) sd_bus_creds_get_uid(creds
, &uid
);
2029 (void) sd_bus_creds_get_tty(creds
, &tty
);
2032 utmp_wall("The system shutdown has been cancelled",
2033 uid_to_name(uid
), tty
, logind_wall_tty_filter
, m
);
2036 return sd_bus_reply_method_return(message
, "b", cancelled
);
2039 static int method_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2040 Manager
*m
= userdata
;
2042 return method_do_shutdown_or_sleep(
2044 SPECIAL_HIBERNATE_TARGET
,
2046 "org.freedesktop.login1.hibernate",
2047 "org.freedesktop.login1.hibernate-multiple-sessions",
2048 "org.freedesktop.login1.hibernate-ignore-inhibit",
2053 static int method_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2054 Manager
*m
= userdata
;
2056 return method_do_shutdown_or_sleep(
2058 SPECIAL_HYBRID_SLEEP_TARGET
,
2060 "org.freedesktop.login1.hibernate",
2061 "org.freedesktop.login1.hibernate-multiple-sessions",
2062 "org.freedesktop.login1.hibernate-ignore-inhibit",
2067 static int method_can_shutdown_or_sleep(
2069 sd_bus_message
*message
,
2072 const char *action_multiple_sessions
,
2073 const char *action_ignore_inhibit
,
2074 const char *sleep_verb
,
2075 sd_bus_error
*error
) {
2077 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2078 bool multiple_sessions
, challenge
, blocked
;
2079 const char *result
= NULL
;
2086 assert(w
<= _INHIBIT_WHAT_MAX
);
2088 assert(action_multiple_sessions
);
2089 assert(action_ignore_inhibit
);
2092 r
= can_sleep(sleep_verb
);
2096 return sd_bus_reply_method_return(message
, "s", "na");
2099 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
2103 r
= sd_bus_creds_get_euid(creds
, &uid
);
2107 r
= have_multiple_sessions(m
, uid
);
2111 multiple_sessions
= r
> 0;
2112 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
2114 if (multiple_sessions
) {
2115 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, UID_INVALID
, &challenge
, error
);
2122 result
= "challenge";
2128 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, UID_INVALID
, &challenge
, error
);
2132 if (r
> 0 && !result
)
2134 else if (challenge
&& (!result
|| streq(result
, "yes")))
2135 result
= "challenge";
2140 if (!multiple_sessions
&& !blocked
) {
2141 /* If neither inhibit nor multiple sessions
2142 * apply then just check the normal policy */
2144 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, NULL
, UID_INVALID
, &challenge
, error
);
2151 result
= "challenge";
2156 return sd_bus_reply_method_return(message
, "s", result
);
2159 static int method_can_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2160 Manager
*m
= userdata
;
2162 return method_can_shutdown_or_sleep(
2165 "org.freedesktop.login1.power-off",
2166 "org.freedesktop.login1.power-off-multiple-sessions",
2167 "org.freedesktop.login1.power-off-ignore-inhibit",
2172 static int method_can_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2173 Manager
*m
= userdata
;
2175 return method_can_shutdown_or_sleep(
2178 "org.freedesktop.login1.reboot",
2179 "org.freedesktop.login1.reboot-multiple-sessions",
2180 "org.freedesktop.login1.reboot-ignore-inhibit",
2185 static int method_can_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2186 Manager
*m
= userdata
;
2188 return method_can_shutdown_or_sleep(
2191 "org.freedesktop.login1.suspend",
2192 "org.freedesktop.login1.suspend-multiple-sessions",
2193 "org.freedesktop.login1.suspend-ignore-inhibit",
2198 static int method_can_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2199 Manager
*m
= userdata
;
2201 return method_can_shutdown_or_sleep(
2204 "org.freedesktop.login1.hibernate",
2205 "org.freedesktop.login1.hibernate-multiple-sessions",
2206 "org.freedesktop.login1.hibernate-ignore-inhibit",
2211 static int method_can_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2212 Manager
*m
= userdata
;
2214 return method_can_shutdown_or_sleep(
2217 "org.freedesktop.login1.hibernate",
2218 "org.freedesktop.login1.hibernate-multiple-sessions",
2219 "org.freedesktop.login1.hibernate-ignore-inhibit",
2224 static int property_get_reboot_to_firmware_setup(
2227 const char *interface
,
2228 const char *property
,
2229 sd_bus_message
*reply
,
2231 sd_bus_error
*error
) {
2238 r
= efi_get_reboot_to_firmware();
2239 if (r
< 0 && r
!= -EOPNOTSUPP
)
2242 return sd_bus_message_append(reply
, "b", r
> 0);
2245 static int method_set_reboot_to_firmware_setup(
2246 sd_bus_message
*message
,
2248 sd_bus_error
*error
) {
2251 Manager
*m
= userdata
;
2256 r
= sd_bus_message_read(message
, "b", &b
);
2260 r
= bus_verify_polkit_async(message
,
2262 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2266 &m
->polkit_registry
,
2271 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2273 r
= efi_set_reboot_to_firmware(b
);
2277 return sd_bus_reply_method_return(message
, NULL
);
2280 static int method_can_reboot_to_firmware_setup(
2281 sd_bus_message
*message
,
2283 sd_bus_error
*error
) {
2288 Manager
*m
= userdata
;
2293 r
= efi_reboot_to_firmware_supported();
2294 if (r
== -EOPNOTSUPP
)
2295 return sd_bus_reply_method_return(message
, "s", "na");
2299 r
= bus_test_polkit(message
,
2301 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2312 result
= "challenge";
2316 return sd_bus_reply_method_return(message
, "s", result
);
2319 static int method_set_wall_message(
2320 sd_bus_message
*message
,
2322 sd_bus_error
*error
) {
2325 Manager
*m
= userdata
;
2327 int enable_wall_messages
;
2332 r
= sd_bus_message_read(message
, "sb", &wall_message
, &enable_wall_messages
);
2336 r
= bus_verify_polkit_async(message
,
2338 "org.freedesktop.login1.set-wall-message",
2342 &m
->polkit_registry
,
2347 return 1; /* Will call us back */
2349 if (isempty(wall_message
))
2350 m
->wall_message
= mfree(m
->wall_message
);
2352 r
= free_and_strdup(&m
->wall_message
, wall_message
);
2357 m
->enable_wall_messages
= enable_wall_messages
;
2359 return sd_bus_reply_method_return(message
, NULL
);
2362 static int method_inhibit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2363 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2364 const char *who
, *why
, *what
, *mode
;
2365 _cleanup_free_
char *id
= NULL
;
2366 _cleanup_close_
int fifo_fd
= -1;
2367 Manager
*m
= userdata
;
2368 Inhibitor
*i
= NULL
;
2378 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2382 w
= inhibit_what_from_string(what
);
2384 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2386 mm
= inhibit_mode_from_string(mode
);
2388 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2390 /* Delay is only supported for shutdown/sleep */
2391 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2392 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2394 /* Don't allow taking delay locks while we are already
2395 * executing the operation. We shouldn't create the impression
2396 * that the lock was successful if the machine is about to go
2397 * down/suspend any moment. */
2398 if (m
->action_what
& w
)
2399 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2401 r
= bus_verify_polkit_async(
2404 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2405 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2406 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2407 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2408 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2409 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2410 "org.freedesktop.login1.inhibit-handle-lid-switch",
2414 &m
->polkit_registry
,
2419 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2421 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2425 r
= sd_bus_creds_get_euid(creds
, &uid
);
2429 r
= sd_bus_creds_get_pid(creds
, &pid
);
2436 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2439 } while (hashmap_get(m
->inhibitors
, id
));
2441 r
= manager_add_inhibitor(m
, id
, &i
);
2449 i
->why
= strdup(why
);
2450 i
->who
= strdup(who
);
2452 if (!i
->why
|| !i
->who
) {
2457 fifo_fd
= inhibitor_create_fifo(i
);
2465 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2474 const sd_bus_vtable manager_vtable
[] = {
2475 SD_BUS_VTABLE_START(0),
2477 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2478 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2480 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2481 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2482 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2483 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2484 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2485 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2486 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2487 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2488 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2489 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2490 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2491 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2492 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2493 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2494 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2495 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2496 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2497 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2498 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2499 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2500 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2501 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2502 SD_BUS_PROPERTY("Docked", "b", property_get_docked
, 0, 0),
2504 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2505 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2506 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2507 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2508 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2509 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2510 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2511 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2512 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2513 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2514 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2515 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2516 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2517 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2518 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2519 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2520 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2521 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2522 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2523 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2524 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2525 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2526 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2527 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2528 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2529 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2530 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2531 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2532 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2533 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2534 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2535 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2536 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2537 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2538 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2539 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2540 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2541 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2542 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2543 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2544 SD_BUS_METHOD("SetWallMessage", "sb", NULL
, method_set_wall_message
, SD_BUS_VTABLE_UNPRIVILEGED
),
2546 SD_BUS_SIGNAL("SessionNew", "so", 0),
2547 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2548 SD_BUS_SIGNAL("UserNew", "uo", 0),
2549 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2550 SD_BUS_SIGNAL("SeatNew", "so", 0),
2551 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2552 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2553 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2558 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2567 if (streq(result
, "done"))
2568 r
= session_send_create_reply(s
, NULL
);
2570 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
2572 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2573 r
= session_send_create_reply(s
, &e
);
2579 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2580 const char *path
, *result
, *unit
;
2581 Manager
*m
= userdata
;
2590 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2592 bus_log_parse_error(r
);
2596 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2597 log_info("Operation '%s' finished.", inhibit_what_to_string(m
->action_what
));
2599 /* Tell people that they now may take a lock again */
2600 send_prepare_for(m
, m
->action_what
, false);
2602 m
->action_job
= mfree(m
->action_job
);
2603 m
->action_unit
= NULL
;
2608 session
= hashmap_get(m
->session_units
, unit
);
2611 if (streq_ptr(path
, session
->scope_job
))
2612 session
->scope_job
= mfree(session
->scope_job
);
2614 session_jobs_reply(session
, unit
, result
);
2616 session_save(session
);
2617 user_save(session
->user
);
2618 session_add_to_gc_queue(session
);
2621 user
= hashmap_get(m
->user_units
, unit
);
2624 if (streq_ptr(path
, user
->service_job
))
2625 user
->service_job
= mfree(user
->service_job
);
2627 if (streq_ptr(path
, user
->slice_job
))
2628 user
->slice_job
= mfree(user
->slice_job
);
2630 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
)
2631 session_jobs_reply(session
, unit
, result
);
2634 user_add_to_gc_queue(user
);
2640 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2641 const char *path
, *unit
;
2642 Manager
*m
= userdata
;
2650 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2652 bus_log_parse_error(r
);
2656 session
= hashmap_get(m
->session_units
, unit
);
2658 session_add_to_gc_queue(session
);
2660 user
= hashmap_get(m
->user_units
, unit
);
2662 user_add_to_gc_queue(user
);
2667 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2668 _cleanup_free_
char *unit
= NULL
;
2669 Manager
*m
= userdata
;
2678 path
= sd_bus_message_get_path(message
);
2682 r
= unit_name_from_dbus_path(path
, &unit
);
2683 if (r
== -EINVAL
) /* not a unit */
2690 session
= hashmap_get(m
->session_units
, unit
);
2692 session_add_to_gc_queue(session
);
2694 user
= hashmap_get(m
->user_units
, unit
);
2696 user_add_to_gc_queue(user
);
2701 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2702 Manager
*m
= userdata
;
2710 r
= sd_bus_message_read(message
, "b", &b
);
2712 bus_log_parse_error(r
);
2719 /* systemd finished reloading, let's recheck all our sessions */
2720 log_debug("System manager has been reloaded, rechecking sessions...");
2722 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2723 session_add_to_gc_queue(session
);
2728 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2733 l
= strv_from_stdarg_alloca(property
);
2735 return sd_bus_emit_properties_changed_strv(
2737 "/org/freedesktop/login1",
2738 "org.freedesktop.login1.Manager",
2742 int manager_start_scope(
2747 const char *description
,
2748 const char *after
, const char *after2
,
2749 sd_bus_error
*error
,
2752 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
2759 r
= sd_bus_message_new_method_call(
2762 "org.freedesktop.systemd1",
2763 "/org/freedesktop/systemd1",
2764 "org.freedesktop.systemd1.Manager",
2765 "StartTransientUnit");
2769 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
2773 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2777 if (!isempty(slice
)) {
2778 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
2783 if (!isempty(description
)) {
2784 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2789 if (!isempty(after
)) {
2790 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2795 if (!isempty(after2
)) {
2796 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2801 /* cgroup empty notification is not available in containers
2802 * currently. To make this less problematic, let's shorten the
2803 * stop timeout for sessions, so that we don't wait
2806 /* Make sure that the session shells are terminated with
2807 * SIGHUP since bash and friends tend to ignore SIGTERM */
2808 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
2812 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
2816 r
= sd_bus_message_close_container(m
);
2820 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2824 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2832 r
= sd_bus_message_read(reply
, "o", &j
);
2846 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2847 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2853 r
= sd_bus_call_method(
2855 "org.freedesktop.systemd1",
2856 "/org/freedesktop/systemd1",
2857 "org.freedesktop.systemd1.Manager",
2861 "ss", unit
, "fail");
2869 r
= sd_bus_message_read(reply
, "o", &j
);
2883 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2884 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2890 r
= sd_bus_call_method(
2892 "org.freedesktop.systemd1",
2893 "/org/freedesktop/systemd1",
2894 "org.freedesktop.systemd1.Manager",
2898 "ss", unit
, "fail");
2900 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2901 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
2906 sd_bus_error_free(error
);
2917 r
= sd_bus_message_read(reply
, "o", &j
);
2931 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
2932 _cleanup_free_
char *path
= NULL
;
2938 path
= unit_dbus_path_from_name(scope
);
2942 r
= sd_bus_call_method(
2944 "org.freedesktop.systemd1",
2946 "org.freedesktop.systemd1.Scope",
2952 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2953 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
2954 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
2955 sd_bus_error_free(error
);
2965 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
2969 return sd_bus_call_method(
2971 "org.freedesktop.systemd1",
2972 "/org/freedesktop/systemd1",
2973 "org.freedesktop.systemd1.Manager",
2977 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
2980 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
2981 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2982 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2983 _cleanup_free_
char *path
= NULL
;
2990 path
= unit_dbus_path_from_name(unit
);
2994 r
= sd_bus_get_property(
2996 "org.freedesktop.systemd1",
2998 "org.freedesktop.systemd1.Unit",
3004 /* systemd might have droppped off momentarily, let's
3005 * not make this an error */
3006 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3007 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3010 /* If the unit is already unloaded then it's not
3012 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3013 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
3019 r
= sd_bus_message_read(reply
, "s", &state
);
3023 return !streq(state
, "inactive") && !streq(state
, "failed");
3026 int manager_job_is_active(Manager
*manager
, const char *path
) {
3027 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3028 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
3034 r
= sd_bus_get_property(
3036 "org.freedesktop.systemd1",
3038 "org.freedesktop.systemd1.Job",
3044 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3045 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3048 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
3054 /* We don't actually care about the state really. The fact
3055 * that we could read the job state is enough for us */