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"
29 #include "alloc-util.h"
30 #include "audit-util.h"
31 #include "bus-common-errors.h"
32 #include "bus-error.h"
34 #include "dirent-util.h"
38 #include "fileio-label.h"
39 #include "formats-util.h"
43 #include "path-util.h"
44 #include "process-util.h"
45 #include "selinux-util.h"
46 #include "sleep-config.h"
49 #include "terminal-util.h"
50 #include "udev-util.h"
51 #include "unit-name.h"
52 #include "user-util.h"
53 #include "utmp-wtmp.h"
55 int manager_get_session_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Session
**ret
) {
56 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
65 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_AUGMENT
, &creds
);
69 r
= sd_bus_creds_get_session(creds
, &name
);
74 session
= hashmap_get(m
->sessions
, name
);
76 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SESSION
, "No session '%s' known", name
);
82 int manager_get_user_from_creds(Manager
*m
, sd_bus_message
*message
, uid_t uid
, sd_bus_error
*error
, User
**ret
) {
90 if (uid
== UID_INVALID
) {
91 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
93 /* Note that we get the owner UID of the session, not the actual client UID here! */
94 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
98 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
103 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
105 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER
, "No user "UID_FMT
" known or logged in", uid
);
111 int manager_get_seat_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Seat
**ret
) {
122 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
126 seat
= session
->seat
;
129 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "Session has no seat.");
131 seat
= hashmap_get(m
->seats
, name
);
133 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", name
);
140 static int property_get_idle_hint(
143 const char *interface
,
144 const char *property
,
145 sd_bus_message
*reply
,
147 sd_bus_error
*error
) {
149 Manager
*m
= userdata
;
155 return sd_bus_message_append(reply
, "b", manager_get_idle_hint(m
, NULL
) > 0);
158 static int property_get_idle_since_hint(
161 const char *interface
,
162 const char *property
,
163 sd_bus_message
*reply
,
165 sd_bus_error
*error
) {
167 Manager
*m
= userdata
;
168 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
174 manager_get_idle_hint(m
, &t
);
176 return sd_bus_message_append(reply
, "t", streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
);
179 static int property_get_inhibited(
182 const char *interface
,
183 const char *property
,
184 sd_bus_message
*reply
,
186 sd_bus_error
*error
) {
188 Manager
*m
= userdata
;
195 w
= manager_inhibit_what(m
, streq(property
, "BlockInhibited") ? INHIBIT_BLOCK
: INHIBIT_DELAY
);
197 return sd_bus_message_append(reply
, "s", inhibit_what_to_string(w
));
200 static int property_get_preparing(
203 const char *interface
,
204 const char *property
,
205 sd_bus_message
*reply
,
207 sd_bus_error
*error
) {
209 Manager
*m
= userdata
;
216 if (streq(property
, "PreparingForShutdown"))
217 b
= !!(m
->action_what
& INHIBIT_SHUTDOWN
);
219 b
= !!(m
->action_what
& INHIBIT_SLEEP
);
221 return sd_bus_message_append(reply
, "b", b
);
224 static int property_get_scheduled_shutdown(
227 const char *interface
,
228 const char *property
,
229 sd_bus_message
*reply
,
231 sd_bus_error
*error
) {
233 Manager
*m
= userdata
;
240 r
= sd_bus_message_open_container(reply
, 'r', "st");
244 r
= sd_bus_message_append(reply
, "st", m
->scheduled_shutdown_type
, m
->scheduled_shutdown_timeout
);
248 return sd_bus_message_close_container(reply
);
251 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action
, handle_action
, HandleAction
);
253 static int property_get_docked(
256 const char *interface
,
257 const char *property
,
258 sd_bus_message
*reply
,
260 sd_bus_error
*error
) {
262 Manager
*m
= userdata
;
268 return sd_bus_message_append(reply
, "b", manager_is_docked_or_external_displays(m
));
271 static int method_get_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
272 _cleanup_free_
char *p
= NULL
;
273 Manager
*m
= userdata
;
281 r
= sd_bus_message_read(message
, "s", &name
);
285 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
289 p
= session_bus_path(session
);
293 return sd_bus_reply_method_return(message
, "o", p
);
296 static int method_get_session_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
297 _cleanup_free_
char *p
= NULL
;
298 Session
*session
= NULL
;
299 Manager
*m
= userdata
;
306 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
308 r
= sd_bus_message_read(message
, "u", &pid
);
313 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
317 r
= manager_get_session_by_pid(m
, pid
, &session
);
322 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
325 p
= session_bus_path(session
);
329 return sd_bus_reply_method_return(message
, "o", p
);
332 static int method_get_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
333 _cleanup_free_
char *p
= NULL
;
334 Manager
*m
= userdata
;
342 r
= sd_bus_message_read(message
, "u", &uid
);
346 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
350 p
= user_bus_path(user
);
354 return sd_bus_reply_method_return(message
, "o", p
);
357 static int method_get_user_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
358 _cleanup_free_
char *p
= NULL
;
359 Manager
*m
= userdata
;
367 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
369 r
= sd_bus_message_read(message
, "u", &pid
);
374 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
378 r
= manager_get_user_by_pid(m
, pid
, &user
);
382 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
);
385 p
= user_bus_path(user
);
389 return sd_bus_reply_method_return(message
, "o", p
);
392 static int method_get_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
393 _cleanup_free_
char *p
= NULL
;
394 Manager
*m
= userdata
;
402 r
= sd_bus_message_read(message
, "s", &name
);
406 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
410 p
= seat_bus_path(seat
);
414 return sd_bus_reply_method_return(message
, "o", p
);
417 static int method_list_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
418 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
419 Manager
*m
= userdata
;
427 r
= sd_bus_message_new_method_return(message
, &reply
);
431 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
435 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
436 _cleanup_free_
char *p
= NULL
;
438 p
= session_bus_path(session
);
442 r
= sd_bus_message_append(reply
, "(susso)",
444 (uint32_t) session
->user
->uid
,
446 session
->seat
? session
->seat
->id
: "",
452 r
= sd_bus_message_close_container(reply
);
456 return sd_bus_send(NULL
, reply
, NULL
);
459 static int method_list_users(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
460 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
461 Manager
*m
= userdata
;
469 r
= sd_bus_message_new_method_return(message
, &reply
);
473 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
477 HASHMAP_FOREACH(user
, m
->users
, i
) {
478 _cleanup_free_
char *p
= NULL
;
480 p
= user_bus_path(user
);
484 r
= sd_bus_message_append(reply
, "(uso)",
485 (uint32_t) user
->uid
,
492 r
= sd_bus_message_close_container(reply
);
496 return sd_bus_send(NULL
, reply
, NULL
);
499 static int method_list_seats(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
500 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
501 Manager
*m
= userdata
;
509 r
= sd_bus_message_new_method_return(message
, &reply
);
513 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
517 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
518 _cleanup_free_
char *p
= NULL
;
520 p
= seat_bus_path(seat
);
524 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
529 r
= sd_bus_message_close_container(reply
);
533 return sd_bus_send(NULL
, reply
, NULL
);
536 static int method_list_inhibitors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
537 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
538 Manager
*m
= userdata
;
539 Inhibitor
*inhibitor
;
546 r
= sd_bus_message_new_method_return(message
, &reply
);
550 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
554 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
556 r
= sd_bus_message_append(reply
, "(ssssuu)",
557 strempty(inhibit_what_to_string(inhibitor
->what
)),
558 strempty(inhibitor
->who
),
559 strempty(inhibitor
->why
),
560 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
561 (uint32_t) inhibitor
->uid
,
562 (uint32_t) inhibitor
->pid
);
567 r
= sd_bus_message_close_container(reply
);
571 return sd_bus_send(NULL
, reply
, NULL
);
574 static int method_create_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
575 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
576 uint32_t uid
, leader
, audit_id
= 0;
577 _cleanup_free_
char *id
= NULL
;
578 Session
*session
= NULL
;
579 Manager
*m
= userdata
;
591 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
596 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
599 t
= _SESSION_TYPE_INVALID
;
601 t
= session_type_from_string(type
);
603 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
607 c
= _SESSION_CLASS_INVALID
;
609 c
= session_class_from_string(class);
611 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
614 if (isempty(desktop
))
617 if (!string_is_safe(desktop
))
618 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
624 seat
= hashmap_get(m
->seats
, cseat
);
626 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
629 if (tty_is_vc(tty
)) {
634 else if (seat
!= m
->seat0
)
635 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
);
637 v
= vtnr_from_tty(tty
);
639 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
643 else if (vtnr
!= (uint32_t) v
)
644 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
646 } else if (tty_is_console(tty
)) {
650 else if (seat
!= m
->seat0
)
651 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
654 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
658 if (seat_has_vts(seat
)) {
659 if (!vtnr
|| vtnr
> 63)
660 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
663 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
667 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
671 if (t
== _SESSION_TYPE_INVALID
) {
672 if (!isempty(display
))
674 else if (!isempty(tty
))
677 t
= SESSION_UNSPECIFIED
;
680 if (c
== _SESSION_CLASS_INVALID
) {
681 if (t
== SESSION_UNSPECIFIED
)
682 c
= SESSION_BACKGROUND
;
688 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
690 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
694 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
699 r
= manager_get_session_by_pid(m
, leader
, NULL
);
701 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already running in a session");
704 * Old gdm and lightdm start the user-session on the same VT as
705 * the greeter session. But they destroy the greeter session
706 * after the user-session and want the user-session to take
707 * over the VT. We need to support this for
708 * backwards-compatibility, so make sure we allow new sessions
709 * on a VT that a greeter is running on. Furthermore, to allow
710 * re-logins, we have to allow a greeter to take over a used VT for
711 * the exact same reasons.
713 if (c
!= SESSION_GREETER
&&
715 vtnr
< m
->seat0
->position_count
&&
716 m
->seat0
->positions
[vtnr
] &&
717 m
->seat0
->positions
[vtnr
]->class != SESSION_GREETER
)
718 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already occupied by a session");
720 audit_session_from_pid(leader
, &audit_id
);
722 /* Keep our session IDs and the audit session IDs in sync */
724 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
727 /* Wut? There's already a session by this name and we
728 * didn't find it above? Weird, then let's not trust
729 * the audit data and let's better register a new
731 if (hashmap_get(m
->sessions
, id
)) {
732 log_warning("Existing logind session ID %s used by new audit session, ignoring", id
);
743 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
746 } while (hashmap_get(m
->sessions
, id
));
749 r
= manager_add_user_by_uid(m
, uid
, &user
);
753 r
= manager_add_session(m
, id
, &session
);
757 session_set_user(session
, user
);
759 session
->leader
= leader
;
760 session
->audit_id
= audit_id
;
763 session
->remote
= remote
;
764 session
->vtnr
= vtnr
;
767 session
->tty
= strdup(tty
);
774 if (!isempty(display
)) {
775 session
->display
= strdup(display
);
776 if (!session
->display
) {
782 if (!isempty(remote_user
)) {
783 session
->remote_user
= strdup(remote_user
);
784 if (!session
->remote_user
) {
790 if (!isempty(remote_host
)) {
791 session
->remote_host
= strdup(remote_host
);
792 if (!session
->remote_host
) {
798 if (!isempty(service
)) {
799 session
->service
= strdup(service
);
800 if (!session
->service
) {
806 if (!isempty(desktop
)) {
807 session
->desktop
= strdup(desktop
);
808 if (!session
->desktop
) {
815 r
= seat_attach_session(seat
, session
);
820 r
= session_start(session
);
824 session
->create_message
= sd_bus_message_ref(message
);
826 /* Now, let's wait until the slice unit and stuff got
827 * created. We send the reply back from
828 * session_send_create_reply(). */
834 session_add_to_gc_queue(session
);
837 user_add_to_gc_queue(user
);
842 static int method_release_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
843 Manager
*m
= userdata
;
851 r
= sd_bus_message_read(message
, "s", &name
);
855 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
859 r
= session_release(session
);
863 return sd_bus_reply_method_return(message
, NULL
);
866 static int method_activate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
867 Manager
*m
= userdata
;
875 r
= sd_bus_message_read(message
, "s", &name
);
879 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
883 return bus_session_method_activate(message
, session
, error
);
886 static int method_activate_session_on_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
887 const char *session_name
, *seat_name
;
888 Manager
*m
= userdata
;
896 /* Same as ActivateSession() but refuses to work if
897 * the seat doesn't match */
899 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
903 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
907 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
911 if (session
->seat
!= seat
)
912 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
914 r
= session_activate(session
);
918 return sd_bus_reply_method_return(message
, NULL
);
921 static int method_lock_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
922 Manager
*m
= userdata
;
930 r
= sd_bus_message_read(message
, "s", &name
);
934 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
938 return bus_session_method_lock(message
, session
, error
);
941 static int method_lock_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
942 Manager
*m
= userdata
;
948 r
= bus_verify_polkit_async(
951 "org.freedesktop.login1.lock-sessions",
960 return 1; /* Will call us back */
962 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
966 return sd_bus_reply_method_return(message
, NULL
);
969 static int method_kill_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
971 Manager
*m
= userdata
;
978 r
= sd_bus_message_read(message
, "s", &name
);
982 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
986 return bus_session_method_kill(message
, session
, error
);
989 static int method_kill_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
990 Manager
*m
= userdata
;
998 r
= sd_bus_message_read(message
, "u", &uid
);
1002 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1006 return bus_user_method_kill(message
, user
, error
);
1009 static int method_terminate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1010 Manager
*m
= userdata
;
1018 r
= sd_bus_message_read(message
, "s", &name
);
1022 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1026 return bus_session_method_terminate(message
, session
, error
);
1029 static int method_terminate_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1030 Manager
*m
= userdata
;
1038 r
= sd_bus_message_read(message
, "u", &uid
);
1042 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1046 return bus_user_method_terminate(message
, user
, error
);
1049 static int method_terminate_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1050 Manager
*m
= userdata
;
1058 r
= sd_bus_message_read(message
, "s", &name
);
1062 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
1066 return bus_seat_method_terminate(message
, seat
, error
);
1069 static int method_set_user_linger(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1070 _cleanup_free_
char *cc
= NULL
;
1071 Manager
*m
= userdata
;
1081 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1085 if (uid
== UID_INVALID
) {
1086 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1088 /* Note that we get the owner UID of the session, not the actual client UID here! */
1089 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1093 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1101 return errno
? -errno
: -ENOENT
;
1103 r
= bus_verify_polkit_async(
1106 "org.freedesktop.login1.set-user-linger",
1110 &m
->polkit_registry
,
1115 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1117 mkdir_p_label("/var/lib/systemd", 0755);
1119 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1123 cc
= cescape(pw
->pw_name
);
1127 path
= strjoina("/var/lib/systemd/linger/", cc
);
1135 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1142 if (r
< 0 && errno
!= ENOENT
)
1145 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1147 user_add_to_gc_queue(u
);
1150 return sd_bus_reply_method_return(message
, NULL
);
1153 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1154 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1155 struct udev_list_entry
*first
, *item
;
1160 e
= udev_enumerate_new(m
->udev
);
1165 r
= udev_enumerate_add_match_parent(e
, d
);
1170 r
= udev_enumerate_scan_devices(e
);
1174 first
= udev_enumerate_get_list_entry(e
);
1175 udev_list_entry_foreach(item
, first
) {
1176 _cleanup_free_
char *t
= NULL
;
1179 p
= udev_list_entry_get_name(item
);
1181 t
= strappend(p
, "/uevent");
1185 write_string_file(t
, "change", WRITE_STRING_FILE_CREATE
);
1191 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1192 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1193 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1194 const char *id_for_seat
;
1201 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1205 if (!udev_device_has_tag(d
, "seat"))
1208 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1212 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1215 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1218 mkdir_p_label("/etc/udev/rules.d", 0755);
1219 mac_selinux_init("/etc");
1220 r
= write_string_file_atomic_label(file
, rule
);
1224 return trigger_device(m
, d
);
1227 static int flush_devices(Manager
*m
) {
1228 _cleanup_closedir_
DIR *d
;
1232 d
= opendir("/etc/udev/rules.d");
1234 if (errno
!= ENOENT
)
1235 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1239 while ((de
= readdir(d
))) {
1241 if (!dirent_is_file(de
))
1244 if (!startswith(de
->d_name
, "72-seat-"))
1247 if (!endswith(de
->d_name
, ".rules"))
1250 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1251 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1255 return trigger_device(m
, NULL
);
1258 static int method_attach_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1259 const char *sysfs
, *seat
;
1260 Manager
*m
= userdata
;
1266 r
= sd_bus_message_read(message
, "ssb", &seat
, &sysfs
, &interactive
);
1270 if (!path_startswith(sysfs
, "/sys"))
1271 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not in /sys", sysfs
);
1273 if (!seat_name_is_valid(seat
))
1274 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat %s is not valid", seat
);
1276 r
= bus_verify_polkit_async(
1279 "org.freedesktop.login1.attach-device",
1283 &m
->polkit_registry
,
1288 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1290 r
= attach_device(m
, seat
, sysfs
);
1294 return sd_bus_reply_method_return(message
, NULL
);
1297 static int method_flush_devices(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1298 Manager
*m
= userdata
;
1304 r
= sd_bus_message_read(message
, "b", &interactive
);
1308 r
= bus_verify_polkit_async(
1311 "org.freedesktop.login1.flush-devices",
1315 &m
->polkit_registry
,
1320 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1322 r
= flush_devices(m
);
1326 return sd_bus_reply_method_return(message
, NULL
);
1329 static int have_multiple_sessions(
1338 /* Check for other users' sessions. Greeter sessions do not
1339 * count, and non-login sessions do not count either. */
1340 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1341 if (session
->class == SESSION_USER
&&
1342 session
->user
->uid
!= uid
)
1348 static int bus_manager_log_shutdown(
1351 const char *unit_name
) {
1358 if (w
!= INHIBIT_SHUTDOWN
)
1361 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1362 p
= "MESSAGE=System is powering down";
1363 q
= "SHUTDOWN=power-off";
1364 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1365 p
= "MESSAGE=System is halting";
1366 q
= "SHUTDOWN=halt";
1367 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1368 p
= "MESSAGE=System is rebooting";
1369 q
= "SHUTDOWN=reboot";
1370 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1371 p
= "MESSAGE=System is rebooting with kexec";
1372 q
= "SHUTDOWN=kexec";
1374 p
= "MESSAGE=System is shutting down";
1378 if (isempty(m
->wall_message
))
1379 p
= strjoina(p
, ".");
1381 p
= strjoina(p
, " (", m
->wall_message
, ").");
1383 return log_struct(LOG_NOTICE
,
1384 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN
),
1390 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1391 Manager
*m
= userdata
;
1396 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1400 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1405 if (until
<= now(CLOCK_MONOTONIC
))
1408 /* We want to ignore the lid switch for a while after each
1409 * suspend, and after boot-up. Hence let's install a timer for
1410 * this. As long as the event source exists we ignore the lid
1413 if (m
->lid_switch_ignore_event_source
) {
1416 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1423 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1425 r
= sd_event_add_time(
1427 &m
->lid_switch_ignore_event_source
,
1430 lid_switch_ignore_handler
, m
);
1435 static void reset_scheduled_shutdown(Manager
*m
) {
1436 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1437 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
1438 m
->nologin_timeout_source
= sd_event_source_unref(m
->nologin_timeout_source
);
1439 m
->scheduled_shutdown_type
= mfree(m
->scheduled_shutdown_type
);
1440 m
->scheduled_shutdown_timeout
= 0;
1441 m
->shutdown_dry_run
= false;
1443 if (m
->unlink_nologin
) {
1444 (void) unlink("/run/nologin");
1445 m
->unlink_nologin
= false;
1449 static int execute_shutdown_or_sleep(
1452 const char *unit_name
,
1453 sd_bus_error
*error
) {
1455 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1462 assert(w
< _INHIBIT_WHAT_MAX
);
1465 bus_manager_log_shutdown(m
, w
, unit_name
);
1467 if (m
->shutdown_dry_run
) {
1468 log_info("Running in dry run, suppressing action.");
1469 reset_scheduled_shutdown(m
);
1471 r
= sd_bus_call_method(
1473 "org.freedesktop.systemd1",
1474 "/org/freedesktop/systemd1",
1475 "org.freedesktop.systemd1.Manager",
1479 "ss", unit_name
, "replace-irreversibly");
1483 r
= sd_bus_message_read(reply
, "o", &p
);
1492 m
->action_unit
= unit_name
;
1493 free(m
->action_job
);
1497 /* Make sure the lid switch is ignored for a while */
1498 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1503 int manager_dispatch_delayed(Manager
*manager
, bool timeout
) {
1505 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1506 Inhibitor
*offending
= NULL
;
1511 if (manager
->action_what
== 0 || manager
->action_job
)
1514 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1515 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1520 (void) get_process_comm(offending
->pid
, &comm
);
1521 u
= uid_to_name(offending
->uid
);
1523 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1524 offending
->uid
, strna(u
),
1525 offending
->pid
, strna(comm
));
1528 /* Actually do the operation */
1529 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1531 log_warning("Failed to send delayed message: %s", bus_error_message(&error
, r
));
1533 manager
->action_unit
= NULL
;
1534 manager
->action_what
= 0;
1541 static int manager_inhibit_timeout_handler(
1546 Manager
*manager
= userdata
;
1550 assert(manager
->inhibit_timeout_source
== s
);
1552 r
= manager_dispatch_delayed(manager
, true);
1553 return (r
< 0) ? r
: 0;
1556 static int delay_shutdown_or_sleep(
1559 const char *unit_name
) {
1566 assert(w
< _INHIBIT_WHAT_MAX
);
1569 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1571 if (m
->inhibit_timeout_source
) {
1572 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1574 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1576 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1578 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1580 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1581 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1586 m
->action_unit
= unit_name
;
1592 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1594 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1595 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1596 [INHIBIT_SLEEP
] = "PrepareForSleep"
1599 int active
= _active
;
1603 assert(w
< _INHIBIT_WHAT_MAX
);
1604 assert(signal_name
[w
]);
1606 return sd_bus_emit_signal(m
->bus
,
1607 "/org/freedesktop/login1",
1608 "org.freedesktop.login1.Manager",
1614 int bus_manager_shutdown_or_sleep_now_or_later(
1616 const char *unit_name
,
1618 sd_bus_error
*error
) {
1626 assert(w
<= _INHIBIT_WHAT_MAX
);
1627 assert(!m
->action_job
);
1629 /* Tell everybody to prepare for shutdown/sleep */
1630 send_prepare_for(m
, w
, true);
1633 m
->inhibit_delay_max
> 0 &&
1634 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1637 /* Shutdown is delayed, keep in mind what we
1638 * want to do, and start a timeout */
1639 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1641 /* Shutdown is not delayed, execute it
1643 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1648 static int verify_shutdown_creds(
1650 sd_bus_message
*message
,
1654 const char *action_multiple_sessions
,
1655 const char *action_ignore_inhibit
,
1656 sd_bus_error
*error
) {
1658 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1659 bool multiple_sessions
, blocked
;
1666 assert(w
<= _INHIBIT_WHAT_MAX
);
1668 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1672 r
= sd_bus_creds_get_euid(creds
, &uid
);
1676 r
= have_multiple_sessions(m
, uid
);
1680 multiple_sessions
= r
> 0;
1681 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1683 if (multiple_sessions
&& action_multiple_sessions
) {
1684 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1688 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1691 if (blocked
&& action_ignore_inhibit
) {
1692 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1696 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1699 if (!multiple_sessions
&& !blocked
&& action
) {
1700 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1704 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1710 static int method_do_shutdown_or_sleep(
1712 sd_bus_message
*message
,
1713 const char *unit_name
,
1716 const char *action_multiple_sessions
,
1717 const char *action_ignore_inhibit
,
1718 const char *sleep_verb
,
1719 sd_bus_error
*error
) {
1727 assert(w
<= _INHIBIT_WHAT_MAX
);
1729 r
= sd_bus_message_read(message
, "b", &interactive
);
1733 /* Don't allow multiple jobs being executed at the same time */
1735 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1738 r
= can_sleep(sleep_verb
);
1743 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1746 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1747 action_ignore_inhibit
, error
);
1751 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1755 return sd_bus_reply_method_return(message
, NULL
);
1758 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1759 Manager
*m
= userdata
;
1761 return method_do_shutdown_or_sleep(
1763 SPECIAL_POWEROFF_TARGET
,
1765 "org.freedesktop.login1.power-off",
1766 "org.freedesktop.login1.power-off-multiple-sessions",
1767 "org.freedesktop.login1.power-off-ignore-inhibit",
1772 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1773 Manager
*m
= userdata
;
1775 return method_do_shutdown_or_sleep(
1777 SPECIAL_REBOOT_TARGET
,
1779 "org.freedesktop.login1.reboot",
1780 "org.freedesktop.login1.reboot-multiple-sessions",
1781 "org.freedesktop.login1.reboot-ignore-inhibit",
1786 static int method_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1787 Manager
*m
= userdata
;
1789 return method_do_shutdown_or_sleep(
1791 SPECIAL_SUSPEND_TARGET
,
1793 "org.freedesktop.login1.suspend",
1794 "org.freedesktop.login1.suspend-multiple-sessions",
1795 "org.freedesktop.login1.suspend-ignore-inhibit",
1800 static int nologin_timeout_handler(
1805 Manager
*m
= userdata
;
1808 log_info("Creating /run/nologin, blocking further logins...");
1810 r
= write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1812 log_error_errno(r
, "Failed to create /run/nologin: %m");
1814 m
->unlink_nologin
= true;
1819 static int update_schedule_file(Manager
*m
) {
1820 _cleanup_free_
char *temp_path
= NULL
;
1821 _cleanup_fclose_
FILE *f
= NULL
;
1826 r
= mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1828 return log_error_errno(r
, "Failed to create shutdown subdirectory: %m");
1830 r
= fopen_temporary("/run/systemd/shutdown/scheduled", &f
, &temp_path
);
1832 return log_error_errno(r
, "Failed to save information about scheduled shutdowns: %m");
1834 (void) fchmod(fileno(f
), 0644);
1840 m
->scheduled_shutdown_timeout
,
1841 m
->enable_wall_messages
,
1842 m
->scheduled_shutdown_type
);
1844 if (!isempty(m
->wall_message
)) {
1845 _cleanup_free_
char *t
;
1847 t
= cescape(m
->wall_message
);
1853 fprintf(f
, "WALL_MESSAGE=%s\n", t
);
1856 r
= fflush_and_check(f
);
1860 if (rename(temp_path
, "/run/systemd/shutdown/scheduled") < 0) {
1868 (void) unlink(temp_path
);
1869 (void) unlink("/run/systemd/shutdown/scheduled");
1871 return log_error_errno(r
, "Failed to write information about scheduled shutdowns: %m");
1874 static int manager_scheduled_shutdown_handler(
1879 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1880 Manager
*m
= userdata
;
1886 if (isempty(m
->scheduled_shutdown_type
))
1889 if (streq(m
->scheduled_shutdown_type
, "halt"))
1890 target
= SPECIAL_HALT_TARGET
;
1891 else if (streq(m
->scheduled_shutdown_type
, "poweroff"))
1892 target
= SPECIAL_POWEROFF_TARGET
;
1894 target
= SPECIAL_REBOOT_TARGET
;
1896 r
= execute_shutdown_or_sleep(m
, 0, target
, &error
);
1898 return log_error_errno(r
, "Unable to execute transition to %s: %m", target
);
1903 static int method_schedule_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1904 Manager
*m
= userdata
;
1905 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1906 const char *action_multiple_sessions
= NULL
;
1907 const char *action_ignore_inhibit
= NULL
;
1908 const char *action
= NULL
;
1916 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
1920 if (startswith(type
, "dry-")) {
1922 m
->shutdown_dry_run
= true;
1925 if (streq(type
, "reboot")) {
1926 action
= "org.freedesktop.login1.reboot";
1927 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
1928 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
1929 } else if (streq(type
, "halt")) {
1930 action
= "org.freedesktop.login1.halt";
1931 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
1932 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
1933 } else if (streq(type
, "poweroff")) {
1934 action
= "org.freedesktop.login1.poweroff";
1935 action_multiple_sessions
= "org.freedesktop.login1.poweroff-multiple-sessions";
1936 action_ignore_inhibit
= "org.freedesktop.login1.poweroff-ignore-inhibit";
1938 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
1940 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
1941 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
1945 if (m
->scheduled_shutdown_timeout_source
) {
1946 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
1948 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1950 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
1952 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1954 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
1955 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
1957 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1960 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
1962 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1966 if (m
->nologin_timeout_source
) {
1967 r
= sd_event_source_set_time(m
->nologin_timeout_source
, elapse
);
1969 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1971 r
= sd_event_source_set_enabled(m
->nologin_timeout_source
, SD_EVENT_ONESHOT
);
1973 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1975 r
= sd_event_add_time(m
->event
, &m
->nologin_timeout_source
,
1976 CLOCK_REALTIME
, elapse
- 5 * USEC_PER_MINUTE
, 0, nologin_timeout_handler
, m
);
1978 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1981 m
->scheduled_shutdown_timeout
= elapse
;
1983 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
1987 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
1988 (void) sd_bus_creds_get_tty(creds
, &tty
);
1990 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
1992 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1997 r
= manager_setup_wall_message_timer(m
);
2001 if (!isempty(type
)) {
2002 r
= update_schedule_file(m
);
2006 (void) unlink("/run/systemd/shutdown/scheduled");
2008 return sd_bus_reply_method_return(message
, NULL
);
2011 static int method_cancel_scheduled_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2012 Manager
*m
= userdata
;
2018 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
2019 reset_scheduled_shutdown(m
);
2022 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2023 const char *tty
= NULL
;
2027 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2029 (void) sd_bus_creds_get_uid(creds
, &uid
);
2030 (void) sd_bus_creds_get_tty(creds
, &tty
);
2033 utmp_wall("The system shutdown has been cancelled",
2034 uid_to_name(uid
), tty
, logind_wall_tty_filter
, m
);
2037 return sd_bus_reply_method_return(message
, "b", cancelled
);
2040 static int method_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2041 Manager
*m
= userdata
;
2043 return method_do_shutdown_or_sleep(
2045 SPECIAL_HIBERNATE_TARGET
,
2047 "org.freedesktop.login1.hibernate",
2048 "org.freedesktop.login1.hibernate-multiple-sessions",
2049 "org.freedesktop.login1.hibernate-ignore-inhibit",
2054 static int method_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2055 Manager
*m
= userdata
;
2057 return method_do_shutdown_or_sleep(
2059 SPECIAL_HYBRID_SLEEP_TARGET
,
2061 "org.freedesktop.login1.hibernate",
2062 "org.freedesktop.login1.hibernate-multiple-sessions",
2063 "org.freedesktop.login1.hibernate-ignore-inhibit",
2068 static int method_can_shutdown_or_sleep(
2070 sd_bus_message
*message
,
2073 const char *action_multiple_sessions
,
2074 const char *action_ignore_inhibit
,
2075 const char *sleep_verb
,
2076 sd_bus_error
*error
) {
2078 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2079 bool multiple_sessions
, challenge
, blocked
;
2080 const char *result
= NULL
;
2087 assert(w
<= _INHIBIT_WHAT_MAX
);
2089 assert(action_multiple_sessions
);
2090 assert(action_ignore_inhibit
);
2093 r
= can_sleep(sleep_verb
);
2097 return sd_bus_reply_method_return(message
, "s", "na");
2100 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
2104 r
= sd_bus_creds_get_euid(creds
, &uid
);
2108 r
= have_multiple_sessions(m
, uid
);
2112 multiple_sessions
= r
> 0;
2113 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
2115 if (multiple_sessions
) {
2116 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, UID_INVALID
, &challenge
, error
);
2123 result
= "challenge";
2129 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, UID_INVALID
, &challenge
, error
);
2133 if (r
> 0 && !result
)
2135 else if (challenge
&& (!result
|| streq(result
, "yes")))
2136 result
= "challenge";
2141 if (!multiple_sessions
&& !blocked
) {
2142 /* If neither inhibit nor multiple sessions
2143 * apply then just check the normal policy */
2145 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, NULL
, UID_INVALID
, &challenge
, error
);
2152 result
= "challenge";
2157 return sd_bus_reply_method_return(message
, "s", result
);
2160 static int method_can_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2161 Manager
*m
= userdata
;
2163 return method_can_shutdown_or_sleep(
2166 "org.freedesktop.login1.power-off",
2167 "org.freedesktop.login1.power-off-multiple-sessions",
2168 "org.freedesktop.login1.power-off-ignore-inhibit",
2173 static int method_can_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2174 Manager
*m
= userdata
;
2176 return method_can_shutdown_or_sleep(
2179 "org.freedesktop.login1.reboot",
2180 "org.freedesktop.login1.reboot-multiple-sessions",
2181 "org.freedesktop.login1.reboot-ignore-inhibit",
2186 static int method_can_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2187 Manager
*m
= userdata
;
2189 return method_can_shutdown_or_sleep(
2192 "org.freedesktop.login1.suspend",
2193 "org.freedesktop.login1.suspend-multiple-sessions",
2194 "org.freedesktop.login1.suspend-ignore-inhibit",
2199 static int method_can_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2200 Manager
*m
= userdata
;
2202 return method_can_shutdown_or_sleep(
2205 "org.freedesktop.login1.hibernate",
2206 "org.freedesktop.login1.hibernate-multiple-sessions",
2207 "org.freedesktop.login1.hibernate-ignore-inhibit",
2212 static int method_can_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2213 Manager
*m
= userdata
;
2215 return method_can_shutdown_or_sleep(
2218 "org.freedesktop.login1.hibernate",
2219 "org.freedesktop.login1.hibernate-multiple-sessions",
2220 "org.freedesktop.login1.hibernate-ignore-inhibit",
2225 static int property_get_reboot_to_firmware_setup(
2228 const char *interface
,
2229 const char *property
,
2230 sd_bus_message
*reply
,
2232 sd_bus_error
*error
) {
2239 r
= efi_get_reboot_to_firmware();
2240 if (r
< 0 && r
!= -EOPNOTSUPP
)
2243 return sd_bus_message_append(reply
, "b", r
> 0);
2246 static int method_set_reboot_to_firmware_setup(
2247 sd_bus_message
*message
,
2249 sd_bus_error
*error
) {
2252 Manager
*m
= userdata
;
2257 r
= sd_bus_message_read(message
, "b", &b
);
2261 r
= bus_verify_polkit_async(message
,
2263 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2267 &m
->polkit_registry
,
2272 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2274 r
= efi_set_reboot_to_firmware(b
);
2278 return sd_bus_reply_method_return(message
, NULL
);
2281 static int method_can_reboot_to_firmware_setup(
2282 sd_bus_message
*message
,
2284 sd_bus_error
*error
) {
2289 Manager
*m
= userdata
;
2294 r
= efi_reboot_to_firmware_supported();
2295 if (r
== -EOPNOTSUPP
)
2296 return sd_bus_reply_method_return(message
, "s", "na");
2300 r
= bus_test_polkit(message
,
2302 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2313 result
= "challenge";
2317 return sd_bus_reply_method_return(message
, "s", result
);
2320 static int method_set_wall_message(
2321 sd_bus_message
*message
,
2323 sd_bus_error
*error
) {
2326 Manager
*m
= userdata
;
2328 int enable_wall_messages
;
2333 r
= sd_bus_message_read(message
, "sb", &wall_message
, &enable_wall_messages
);
2337 r
= bus_verify_polkit_async(message
,
2339 "org.freedesktop.login1.set-wall-message",
2343 &m
->polkit_registry
,
2348 return 1; /* Will call us back */
2350 if (isempty(wall_message
))
2351 m
->wall_message
= mfree(m
->wall_message
);
2353 r
= free_and_strdup(&m
->wall_message
, wall_message
);
2358 m
->enable_wall_messages
= enable_wall_messages
;
2360 return sd_bus_reply_method_return(message
, NULL
);
2363 static int method_inhibit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2364 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2365 const char *who
, *why
, *what
, *mode
;
2366 _cleanup_free_
char *id
= NULL
;
2367 _cleanup_close_
int fifo_fd
= -1;
2368 Manager
*m
= userdata
;
2369 Inhibitor
*i
= NULL
;
2379 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2383 w
= inhibit_what_from_string(what
);
2385 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2387 mm
= inhibit_mode_from_string(mode
);
2389 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2391 /* Delay is only supported for shutdown/sleep */
2392 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2393 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2395 /* Don't allow taking delay locks while we are already
2396 * executing the operation. We shouldn't create the impression
2397 * that the lock was successful if the machine is about to go
2398 * down/suspend any moment. */
2399 if (m
->action_what
& w
)
2400 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2402 r
= bus_verify_polkit_async(
2405 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2406 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2407 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2408 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2409 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2410 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2411 "org.freedesktop.login1.inhibit-handle-lid-switch",
2415 &m
->polkit_registry
,
2420 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2422 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2426 r
= sd_bus_creds_get_euid(creds
, &uid
);
2430 r
= sd_bus_creds_get_pid(creds
, &pid
);
2437 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2440 } while (hashmap_get(m
->inhibitors
, id
));
2442 r
= manager_add_inhibitor(m
, id
, &i
);
2450 i
->why
= strdup(why
);
2451 i
->who
= strdup(who
);
2453 if (!i
->why
|| !i
->who
) {
2458 fifo_fd
= inhibitor_create_fifo(i
);
2466 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2475 const sd_bus_vtable manager_vtable
[] = {
2476 SD_BUS_VTABLE_START(0),
2478 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2479 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2481 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2482 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2483 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2484 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2485 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2486 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2487 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2488 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2489 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2490 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2491 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2492 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2493 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2494 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2495 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2496 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2497 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2498 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2499 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2500 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2501 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2502 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2503 SD_BUS_PROPERTY("Docked", "b", property_get_docked
, 0, 0),
2505 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2506 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2507 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2508 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2509 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2510 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2511 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2512 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2513 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2514 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2515 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2516 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2517 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2518 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2519 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2520 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2521 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2522 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2523 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2524 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2525 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2526 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2527 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2528 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2529 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2530 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2531 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2532 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2533 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2534 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2535 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2536 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2537 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2538 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2539 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2540 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2541 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2542 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2543 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2544 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2545 SD_BUS_METHOD("SetWallMessage", "sb", NULL
, method_set_wall_message
, SD_BUS_VTABLE_UNPRIVILEGED
),
2547 SD_BUS_SIGNAL("SessionNew", "so", 0),
2548 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2549 SD_BUS_SIGNAL("UserNew", "uo", 0),
2550 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2551 SD_BUS_SIGNAL("SeatNew", "so", 0),
2552 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2553 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2554 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2559 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2568 if (streq(result
, "done"))
2569 r
= session_send_create_reply(s
, NULL
);
2571 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
2573 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2574 r
= session_send_create_reply(s
, &e
);
2580 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2581 const char *path
, *result
, *unit
;
2582 Manager
*m
= userdata
;
2591 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2593 bus_log_parse_error(r
);
2597 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2598 log_info("Operation '%s' finished.", inhibit_what_to_string(m
->action_what
));
2600 /* Tell people that they now may take a lock again */
2601 send_prepare_for(m
, m
->action_what
, false);
2603 m
->action_job
= mfree(m
->action_job
);
2604 m
->action_unit
= NULL
;
2609 session
= hashmap_get(m
->session_units
, unit
);
2612 if (streq_ptr(path
, session
->scope_job
))
2613 session
->scope_job
= mfree(session
->scope_job
);
2615 session_jobs_reply(session
, unit
, result
);
2617 session_save(session
);
2618 user_save(session
->user
);
2619 session_add_to_gc_queue(session
);
2622 user
= hashmap_get(m
->user_units
, unit
);
2625 if (streq_ptr(path
, user
->service_job
))
2626 user
->service_job
= mfree(user
->service_job
);
2628 if (streq_ptr(path
, user
->slice_job
))
2629 user
->slice_job
= mfree(user
->slice_job
);
2631 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
)
2632 session_jobs_reply(session
, unit
, result
);
2635 user_add_to_gc_queue(user
);
2641 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2642 const char *path
, *unit
;
2643 Manager
*m
= userdata
;
2651 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2653 bus_log_parse_error(r
);
2657 session
= hashmap_get(m
->session_units
, unit
);
2659 session_add_to_gc_queue(session
);
2661 user
= hashmap_get(m
->user_units
, unit
);
2663 user_add_to_gc_queue(user
);
2668 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2669 _cleanup_free_
char *unit
= NULL
;
2670 Manager
*m
= userdata
;
2679 path
= sd_bus_message_get_path(message
);
2683 r
= unit_name_from_dbus_path(path
, &unit
);
2684 if (r
== -EINVAL
) /* not a unit */
2691 session
= hashmap_get(m
->session_units
, unit
);
2693 session_add_to_gc_queue(session
);
2695 user
= hashmap_get(m
->user_units
, unit
);
2697 user_add_to_gc_queue(user
);
2702 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2703 Manager
*m
= userdata
;
2711 r
= sd_bus_message_read(message
, "b", &b
);
2713 bus_log_parse_error(r
);
2720 /* systemd finished reloading, let's recheck all our sessions */
2721 log_debug("System manager has been reloaded, rechecking sessions...");
2723 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2724 session_add_to_gc_queue(session
);
2729 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2734 l
= strv_from_stdarg_alloca(property
);
2736 return sd_bus_emit_properties_changed_strv(
2738 "/org/freedesktop/login1",
2739 "org.freedesktop.login1.Manager",
2743 int manager_start_slice(
2746 const char *description
,
2750 sd_bus_error
*error
,
2753 _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(slice
), "fail");
2773 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2777 if (!isempty(description
)) {
2778 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2783 if (!isempty(after
)) {
2784 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2789 if (!isempty(after2
)) {
2790 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2795 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
2799 r
= sd_bus_message_close_container(m
);
2803 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2807 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2815 r
= sd_bus_message_read(reply
, "o", &j
);
2829 int manager_start_scope(
2834 const char *description
,
2838 sd_bus_error
*error
,
2841 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
2848 r
= sd_bus_message_new_method_call(
2851 "org.freedesktop.systemd1",
2852 "/org/freedesktop/systemd1",
2853 "org.freedesktop.systemd1.Manager",
2854 "StartTransientUnit");
2858 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
2862 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2866 if (!isempty(slice
)) {
2867 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
2872 if (!isempty(description
)) {
2873 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2878 if (!isempty(after
)) {
2879 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2884 if (!isempty(after2
)) {
2885 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2890 /* cgroup empty notification is not available in containers
2891 * currently. To make this less problematic, let's shorten the
2892 * stop timeout for sessions, so that we don't wait
2895 /* Make sure that the session shells are terminated with
2896 * SIGHUP since bash and friends tend to ignore SIGTERM */
2897 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
2901 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
2905 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
2909 r
= sd_bus_message_close_container(m
);
2913 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2917 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2925 r
= sd_bus_message_read(reply
, "o", &j
);
2939 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2940 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2946 r
= sd_bus_call_method(
2948 "org.freedesktop.systemd1",
2949 "/org/freedesktop/systemd1",
2950 "org.freedesktop.systemd1.Manager",
2954 "ss", unit
, "fail");
2962 r
= sd_bus_message_read(reply
, "o", &j
);
2976 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2977 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2983 r
= sd_bus_call_method(
2985 "org.freedesktop.systemd1",
2986 "/org/freedesktop/systemd1",
2987 "org.freedesktop.systemd1.Manager",
2991 "ss", unit
, "fail");
2993 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2994 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
2999 sd_bus_error_free(error
);
3010 r
= sd_bus_message_read(reply
, "o", &j
);
3024 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
3025 _cleanup_free_
char *path
= NULL
;
3031 path
= unit_dbus_path_from_name(scope
);
3035 r
= sd_bus_call_method(
3037 "org.freedesktop.systemd1",
3039 "org.freedesktop.systemd1.Scope",
3045 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3046 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
3047 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
3048 sd_bus_error_free(error
);
3058 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
3062 return sd_bus_call_method(
3064 "org.freedesktop.systemd1",
3065 "/org/freedesktop/systemd1",
3066 "org.freedesktop.systemd1.Manager",
3070 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
3073 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
3074 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3075 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
3076 _cleanup_free_
char *path
= NULL
;
3083 path
= unit_dbus_path_from_name(unit
);
3087 r
= sd_bus_get_property(
3089 "org.freedesktop.systemd1",
3091 "org.freedesktop.systemd1.Unit",
3097 /* systemd might have droppped off momentarily, let's
3098 * not make this an error */
3099 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3100 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3103 /* If the unit is already unloaded then it's not
3105 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3106 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
3112 r
= sd_bus_message_read(reply
, "s", &state
);
3116 return !streq(state
, "inactive") && !streq(state
, "failed");
3119 int manager_job_is_active(Manager
*manager
, const char *path
) {
3120 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3121 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
3127 r
= sd_bus_get_property(
3129 "org.freedesktop.systemd1",
3131 "org.freedesktop.systemd1.Job",
3137 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3138 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3141 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
3147 /* We don't actually care about the state really. The fact
3148 * that we could read the job state is enough for us */