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
);
315 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
319 r
= manager_get_session_by_pid(m
, pid
, &session
);
324 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
327 p
= session_bus_path(session
);
331 return sd_bus_reply_method_return(message
, "o", p
);
334 static int method_get_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
335 _cleanup_free_
char *p
= NULL
;
336 Manager
*m
= userdata
;
344 r
= sd_bus_message_read(message
, "u", &uid
);
348 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
352 p
= user_bus_path(user
);
356 return sd_bus_reply_method_return(message
, "o", p
);
359 static int method_get_user_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
360 _cleanup_free_
char *p
= NULL
;
361 Manager
*m
= userdata
;
369 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
371 r
= sd_bus_message_read(message
, "u", &pid
);
378 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
382 r
= manager_get_user_by_pid(m
, pid
, &user
);
386 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
);
389 p
= user_bus_path(user
);
393 return sd_bus_reply_method_return(message
, "o", p
);
396 static int method_get_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
397 _cleanup_free_
char *p
= NULL
;
398 Manager
*m
= userdata
;
406 r
= sd_bus_message_read(message
, "s", &name
);
410 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
414 p
= seat_bus_path(seat
);
418 return sd_bus_reply_method_return(message
, "o", p
);
421 static int method_list_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
422 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
423 Manager
*m
= userdata
;
431 r
= sd_bus_message_new_method_return(message
, &reply
);
435 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
439 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
440 _cleanup_free_
char *p
= NULL
;
442 p
= session_bus_path(session
);
446 r
= sd_bus_message_append(reply
, "(susso)",
448 (uint32_t) session
->user
->uid
,
450 session
->seat
? session
->seat
->id
: "",
456 r
= sd_bus_message_close_container(reply
);
460 return sd_bus_send(NULL
, reply
, NULL
);
463 static int method_list_users(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
464 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
465 Manager
*m
= userdata
;
473 r
= sd_bus_message_new_method_return(message
, &reply
);
477 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
481 HASHMAP_FOREACH(user
, m
->users
, i
) {
482 _cleanup_free_
char *p
= NULL
;
484 p
= user_bus_path(user
);
488 r
= sd_bus_message_append(reply
, "(uso)",
489 (uint32_t) user
->uid
,
496 r
= sd_bus_message_close_container(reply
);
500 return sd_bus_send(NULL
, reply
, NULL
);
503 static int method_list_seats(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
504 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
505 Manager
*m
= userdata
;
513 r
= sd_bus_message_new_method_return(message
, &reply
);
517 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
521 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
522 _cleanup_free_
char *p
= NULL
;
524 p
= seat_bus_path(seat
);
528 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
533 r
= sd_bus_message_close_container(reply
);
537 return sd_bus_send(NULL
, reply
, NULL
);
540 static int method_list_inhibitors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
541 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
542 Manager
*m
= userdata
;
543 Inhibitor
*inhibitor
;
550 r
= sd_bus_message_new_method_return(message
, &reply
);
554 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
558 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
560 r
= sd_bus_message_append(reply
, "(ssssuu)",
561 strempty(inhibit_what_to_string(inhibitor
->what
)),
562 strempty(inhibitor
->who
),
563 strempty(inhibitor
->why
),
564 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
565 (uint32_t) inhibitor
->uid
,
566 (uint32_t) inhibitor
->pid
);
571 r
= sd_bus_message_close_container(reply
);
575 return sd_bus_send(NULL
, reply
, NULL
);
578 static int method_create_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
579 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
580 uint32_t audit_id
= 0;
581 _cleanup_free_
char *id
= NULL
;
582 Session
*session
= NULL
;
583 Manager
*m
= userdata
;
597 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
598 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
600 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
604 if (!uid_is_valid(uid
))
605 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid UID");
606 if (leader
< 0 || leader
== 1)
607 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
610 t
= _SESSION_TYPE_INVALID
;
612 t
= session_type_from_string(type
);
614 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
618 c
= _SESSION_CLASS_INVALID
;
620 c
= session_class_from_string(class);
622 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
625 if (isempty(desktop
))
628 if (!string_is_safe(desktop
))
629 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
635 seat
= hashmap_get(m
->seats
, cseat
);
637 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
640 if (tty_is_vc(tty
)) {
645 else if (seat
!= m
->seat0
)
646 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
);
648 v
= vtnr_from_tty(tty
);
650 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
654 else if (vtnr
!= (uint32_t) v
)
655 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
657 } else if (tty_is_console(tty
)) {
661 else if (seat
!= m
->seat0
)
662 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
665 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
669 if (seat_has_vts(seat
)) {
670 if (!vtnr
|| vtnr
> 63)
671 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
674 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
678 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
682 if (t
== _SESSION_TYPE_INVALID
) {
683 if (!isempty(display
))
685 else if (!isempty(tty
))
688 t
= SESSION_UNSPECIFIED
;
691 if (c
== _SESSION_CLASS_INVALID
) {
692 if (t
== SESSION_UNSPECIFIED
)
693 c
= SESSION_BACKGROUND
;
699 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
701 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
705 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
710 r
= manager_get_session_by_pid(m
, leader
, NULL
);
712 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already running in a session");
715 * Old gdm and lightdm start the user-session on the same VT as
716 * the greeter session. But they destroy the greeter session
717 * after the user-session and want the user-session to take
718 * over the VT. We need to support this for
719 * backwards-compatibility, so make sure we allow new sessions
720 * on a VT that a greeter is running on. Furthermore, to allow
721 * re-logins, we have to allow a greeter to take over a used VT for
722 * the exact same reasons.
724 if (c
!= SESSION_GREETER
&&
726 vtnr
< m
->seat0
->position_count
&&
727 m
->seat0
->positions
[vtnr
] &&
728 m
->seat0
->positions
[vtnr
]->class != SESSION_GREETER
)
729 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already occupied by a session");
731 audit_session_from_pid(leader
, &audit_id
);
733 /* Keep our session IDs and the audit session IDs in sync */
735 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
738 /* Wut? There's already a session by this name and we
739 * didn't find it above? Weird, then let's not trust
740 * the audit data and let's better register a new
742 if (hashmap_get(m
->sessions
, id
)) {
743 log_warning("Existing logind session ID %s used by new audit session, ignoring", id
);
754 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
757 } while (hashmap_get(m
->sessions
, id
));
760 r
= manager_add_user_by_uid(m
, uid
, &user
);
764 r
= manager_add_session(m
, id
, &session
);
768 session_set_user(session
, user
);
770 session
->leader
= leader
;
771 session
->audit_id
= audit_id
;
774 session
->remote
= remote
;
775 session
->vtnr
= vtnr
;
778 session
->tty
= strdup(tty
);
785 if (!isempty(display
)) {
786 session
->display
= strdup(display
);
787 if (!session
->display
) {
793 if (!isempty(remote_user
)) {
794 session
->remote_user
= strdup(remote_user
);
795 if (!session
->remote_user
) {
801 if (!isempty(remote_host
)) {
802 session
->remote_host
= strdup(remote_host
);
803 if (!session
->remote_host
) {
809 if (!isempty(service
)) {
810 session
->service
= strdup(service
);
811 if (!session
->service
) {
817 if (!isempty(desktop
)) {
818 session
->desktop
= strdup(desktop
);
819 if (!session
->desktop
) {
826 r
= seat_attach_session(seat
, session
);
831 r
= session_start(session
);
835 session
->create_message
= sd_bus_message_ref(message
);
837 /* Now, let's wait until the slice unit and stuff got
838 * created. We send the reply back from
839 * session_send_create_reply(). */
845 session_add_to_gc_queue(session
);
848 user_add_to_gc_queue(user
);
853 static int method_release_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
854 Manager
*m
= userdata
;
862 r
= sd_bus_message_read(message
, "s", &name
);
866 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
870 r
= session_release(session
);
874 return sd_bus_reply_method_return(message
, NULL
);
877 static int method_activate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
878 Manager
*m
= userdata
;
886 r
= sd_bus_message_read(message
, "s", &name
);
890 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
894 return bus_session_method_activate(message
, session
, error
);
897 static int method_activate_session_on_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
898 const char *session_name
, *seat_name
;
899 Manager
*m
= userdata
;
907 /* Same as ActivateSession() but refuses to work if
908 * the seat doesn't match */
910 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
914 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
918 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
922 if (session
->seat
!= seat
)
923 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
925 r
= session_activate(session
);
929 return sd_bus_reply_method_return(message
, NULL
);
932 static int method_lock_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
933 Manager
*m
= userdata
;
941 r
= sd_bus_message_read(message
, "s", &name
);
945 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
949 return bus_session_method_lock(message
, session
, error
);
952 static int method_lock_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
953 Manager
*m
= userdata
;
959 r
= bus_verify_polkit_async(
962 "org.freedesktop.login1.lock-sessions",
971 return 1; /* Will call us back */
973 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
977 return sd_bus_reply_method_return(message
, NULL
);
980 static int method_kill_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
982 Manager
*m
= userdata
;
989 r
= sd_bus_message_read(message
, "s", &name
);
993 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
997 return bus_session_method_kill(message
, session
, error
);
1000 static int method_kill_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1001 Manager
*m
= userdata
;
1009 r
= sd_bus_message_read(message
, "u", &uid
);
1013 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1017 return bus_user_method_kill(message
, user
, error
);
1020 static int method_terminate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1021 Manager
*m
= userdata
;
1029 r
= sd_bus_message_read(message
, "s", &name
);
1033 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1037 return bus_session_method_terminate(message
, session
, error
);
1040 static int method_terminate_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1041 Manager
*m
= userdata
;
1049 r
= sd_bus_message_read(message
, "u", &uid
);
1053 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1057 return bus_user_method_terminate(message
, user
, error
);
1060 static int method_terminate_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1061 Manager
*m
= userdata
;
1069 r
= sd_bus_message_read(message
, "s", &name
);
1073 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
1077 return bus_seat_method_terminate(message
, seat
, error
);
1080 static int method_set_user_linger(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1081 _cleanup_free_
char *cc
= NULL
;
1082 Manager
*m
= userdata
;
1092 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1096 if (uid
== UID_INVALID
) {
1097 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1099 /* Note that we get the owner UID of the session, not the actual client UID here! */
1100 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1104 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1108 } else if (!uid_is_valid(uid
))
1114 return errno
? -errno
: -ENOENT
;
1116 r
= bus_verify_polkit_async(
1119 "org.freedesktop.login1.set-user-linger",
1123 &m
->polkit_registry
,
1128 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1130 mkdir_p_label("/var/lib/systemd", 0755);
1132 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1136 cc
= cescape(pw
->pw_name
);
1140 path
= strjoina("/var/lib/systemd/linger/", cc
);
1148 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1155 if (r
< 0 && errno
!= ENOENT
)
1158 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1160 user_add_to_gc_queue(u
);
1163 return sd_bus_reply_method_return(message
, NULL
);
1166 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1167 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1168 struct udev_list_entry
*first
, *item
;
1173 e
= udev_enumerate_new(m
->udev
);
1178 r
= udev_enumerate_add_match_parent(e
, d
);
1183 r
= udev_enumerate_scan_devices(e
);
1187 first
= udev_enumerate_get_list_entry(e
);
1188 udev_list_entry_foreach(item
, first
) {
1189 _cleanup_free_
char *t
= NULL
;
1192 p
= udev_list_entry_get_name(item
);
1194 t
= strappend(p
, "/uevent");
1198 write_string_file(t
, "change", WRITE_STRING_FILE_CREATE
);
1204 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1205 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1206 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1207 const char *id_for_seat
;
1214 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1218 if (!udev_device_has_tag(d
, "seat"))
1221 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1225 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1228 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1231 mkdir_p_label("/etc/udev/rules.d", 0755);
1232 mac_selinux_init("/etc");
1233 r
= write_string_file_atomic_label(file
, rule
);
1237 return trigger_device(m
, d
);
1240 static int flush_devices(Manager
*m
) {
1241 _cleanup_closedir_
DIR *d
;
1245 d
= opendir("/etc/udev/rules.d");
1247 if (errno
!= ENOENT
)
1248 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1252 while ((de
= readdir(d
))) {
1254 if (!dirent_is_file(de
))
1257 if (!startswith(de
->d_name
, "72-seat-"))
1260 if (!endswith(de
->d_name
, ".rules"))
1263 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1264 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1268 return trigger_device(m
, NULL
);
1271 static int method_attach_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1272 const char *sysfs
, *seat
;
1273 Manager
*m
= userdata
;
1279 r
= sd_bus_message_read(message
, "ssb", &seat
, &sysfs
, &interactive
);
1283 if (!path_startswith(sysfs
, "/sys"))
1284 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not in /sys", sysfs
);
1286 if (!seat_name_is_valid(seat
))
1287 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat %s is not valid", seat
);
1289 r
= bus_verify_polkit_async(
1292 "org.freedesktop.login1.attach-device",
1296 &m
->polkit_registry
,
1301 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1303 r
= attach_device(m
, seat
, sysfs
);
1307 return sd_bus_reply_method_return(message
, NULL
);
1310 static int method_flush_devices(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1311 Manager
*m
= userdata
;
1317 r
= sd_bus_message_read(message
, "b", &interactive
);
1321 r
= bus_verify_polkit_async(
1324 "org.freedesktop.login1.flush-devices",
1328 &m
->polkit_registry
,
1333 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1335 r
= flush_devices(m
);
1339 return sd_bus_reply_method_return(message
, NULL
);
1342 static int have_multiple_sessions(
1351 /* Check for other users' sessions. Greeter sessions do not
1352 * count, and non-login sessions do not count either. */
1353 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1354 if (session
->class == SESSION_USER
&&
1355 session
->user
->uid
!= uid
)
1361 static int bus_manager_log_shutdown(
1364 const char *unit_name
) {
1371 if (w
!= INHIBIT_SHUTDOWN
)
1374 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1375 p
= "MESSAGE=System is powering down";
1376 q
= "SHUTDOWN=power-off";
1377 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1378 p
= "MESSAGE=System is halting";
1379 q
= "SHUTDOWN=halt";
1380 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1381 p
= "MESSAGE=System is rebooting";
1382 q
= "SHUTDOWN=reboot";
1383 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1384 p
= "MESSAGE=System is rebooting with kexec";
1385 q
= "SHUTDOWN=kexec";
1387 p
= "MESSAGE=System is shutting down";
1391 if (isempty(m
->wall_message
))
1392 p
= strjoina(p
, ".");
1394 p
= strjoina(p
, " (", m
->wall_message
, ").");
1396 return log_struct(LOG_NOTICE
,
1397 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN
),
1403 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1404 Manager
*m
= userdata
;
1409 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1413 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1418 if (until
<= now(CLOCK_MONOTONIC
))
1421 /* We want to ignore the lid switch for a while after each
1422 * suspend, and after boot-up. Hence let's install a timer for
1423 * this. As long as the event source exists we ignore the lid
1426 if (m
->lid_switch_ignore_event_source
) {
1429 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1436 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1438 r
= sd_event_add_time(
1440 &m
->lid_switch_ignore_event_source
,
1443 lid_switch_ignore_handler
, m
);
1448 static void reset_scheduled_shutdown(Manager
*m
) {
1449 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1450 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
1451 m
->nologin_timeout_source
= sd_event_source_unref(m
->nologin_timeout_source
);
1452 m
->scheduled_shutdown_type
= mfree(m
->scheduled_shutdown_type
);
1453 m
->scheduled_shutdown_timeout
= 0;
1454 m
->shutdown_dry_run
= false;
1456 if (m
->unlink_nologin
) {
1457 (void) unlink("/run/nologin");
1458 m
->unlink_nologin
= false;
1462 static int execute_shutdown_or_sleep(
1465 const char *unit_name
,
1466 sd_bus_error
*error
) {
1468 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1475 assert(w
< _INHIBIT_WHAT_MAX
);
1478 bus_manager_log_shutdown(m
, w
, unit_name
);
1480 if (m
->shutdown_dry_run
) {
1481 log_info("Running in dry run, suppressing action.");
1482 reset_scheduled_shutdown(m
);
1484 r
= sd_bus_call_method(
1486 "org.freedesktop.systemd1",
1487 "/org/freedesktop/systemd1",
1488 "org.freedesktop.systemd1.Manager",
1492 "ss", unit_name
, "replace-irreversibly");
1496 r
= sd_bus_message_read(reply
, "o", &p
);
1505 m
->action_unit
= unit_name
;
1506 free(m
->action_job
);
1510 /* Make sure the lid switch is ignored for a while */
1511 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1516 int manager_dispatch_delayed(Manager
*manager
, bool timeout
) {
1518 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1519 Inhibitor
*offending
= NULL
;
1524 if (manager
->action_what
== 0 || manager
->action_job
)
1527 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1528 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1533 (void) get_process_comm(offending
->pid
, &comm
);
1534 u
= uid_to_name(offending
->uid
);
1536 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1537 offending
->uid
, strna(u
),
1538 offending
->pid
, strna(comm
));
1541 /* Actually do the operation */
1542 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1544 log_warning("Failed to send delayed message: %s", bus_error_message(&error
, r
));
1546 manager
->action_unit
= NULL
;
1547 manager
->action_what
= 0;
1554 static int manager_inhibit_timeout_handler(
1559 Manager
*manager
= userdata
;
1563 assert(manager
->inhibit_timeout_source
== s
);
1565 r
= manager_dispatch_delayed(manager
, true);
1566 return (r
< 0) ? r
: 0;
1569 static int delay_shutdown_or_sleep(
1572 const char *unit_name
) {
1579 assert(w
< _INHIBIT_WHAT_MAX
);
1582 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1584 if (m
->inhibit_timeout_source
) {
1585 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1587 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1589 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1591 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1593 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1594 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1599 m
->action_unit
= unit_name
;
1605 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1607 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1608 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1609 [INHIBIT_SLEEP
] = "PrepareForSleep"
1612 int active
= _active
;
1616 assert(w
< _INHIBIT_WHAT_MAX
);
1617 assert(signal_name
[w
]);
1619 return sd_bus_emit_signal(m
->bus
,
1620 "/org/freedesktop/login1",
1621 "org.freedesktop.login1.Manager",
1627 int bus_manager_shutdown_or_sleep_now_or_later(
1629 const char *unit_name
,
1631 sd_bus_error
*error
) {
1639 assert(w
<= _INHIBIT_WHAT_MAX
);
1640 assert(!m
->action_job
);
1642 /* Tell everybody to prepare for shutdown/sleep */
1643 send_prepare_for(m
, w
, true);
1646 m
->inhibit_delay_max
> 0 &&
1647 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1650 /* Shutdown is delayed, keep in mind what we
1651 * want to do, and start a timeout */
1652 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1654 /* Shutdown is not delayed, execute it
1656 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1661 static int verify_shutdown_creds(
1663 sd_bus_message
*message
,
1667 const char *action_multiple_sessions
,
1668 const char *action_ignore_inhibit
,
1669 sd_bus_error
*error
) {
1671 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1672 bool multiple_sessions
, blocked
;
1679 assert(w
<= _INHIBIT_WHAT_MAX
);
1681 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1685 r
= sd_bus_creds_get_euid(creds
, &uid
);
1689 r
= have_multiple_sessions(m
, uid
);
1693 multiple_sessions
= r
> 0;
1694 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1696 if (multiple_sessions
&& action_multiple_sessions
) {
1697 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1701 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1704 if (blocked
&& action_ignore_inhibit
) {
1705 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1709 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1712 if (!multiple_sessions
&& !blocked
&& action
) {
1713 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1717 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1723 static int method_do_shutdown_or_sleep(
1725 sd_bus_message
*message
,
1726 const char *unit_name
,
1729 const char *action_multiple_sessions
,
1730 const char *action_ignore_inhibit
,
1731 const char *sleep_verb
,
1732 sd_bus_error
*error
) {
1740 assert(w
<= _INHIBIT_WHAT_MAX
);
1742 r
= sd_bus_message_read(message
, "b", &interactive
);
1746 /* Don't allow multiple jobs being executed at the same time */
1748 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1751 r
= can_sleep(sleep_verb
);
1756 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1759 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1760 action_ignore_inhibit
, error
);
1764 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1768 return sd_bus_reply_method_return(message
, NULL
);
1771 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1772 Manager
*m
= userdata
;
1774 return method_do_shutdown_or_sleep(
1776 SPECIAL_POWEROFF_TARGET
,
1778 "org.freedesktop.login1.power-off",
1779 "org.freedesktop.login1.power-off-multiple-sessions",
1780 "org.freedesktop.login1.power-off-ignore-inhibit",
1785 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1786 Manager
*m
= userdata
;
1788 return method_do_shutdown_or_sleep(
1790 SPECIAL_REBOOT_TARGET
,
1792 "org.freedesktop.login1.reboot",
1793 "org.freedesktop.login1.reboot-multiple-sessions",
1794 "org.freedesktop.login1.reboot-ignore-inhibit",
1799 static int method_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1800 Manager
*m
= userdata
;
1802 return method_do_shutdown_or_sleep(
1804 SPECIAL_SUSPEND_TARGET
,
1806 "org.freedesktop.login1.suspend",
1807 "org.freedesktop.login1.suspend-multiple-sessions",
1808 "org.freedesktop.login1.suspend-ignore-inhibit",
1813 static int nologin_timeout_handler(
1818 Manager
*m
= userdata
;
1821 log_info("Creating /run/nologin, blocking further logins...");
1823 r
= write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
1825 log_error_errno(r
, "Failed to create /run/nologin: %m");
1827 m
->unlink_nologin
= true;
1832 static int update_schedule_file(Manager
*m
) {
1833 _cleanup_free_
char *temp_path
= NULL
;
1834 _cleanup_fclose_
FILE *f
= NULL
;
1839 r
= mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1841 return log_error_errno(r
, "Failed to create shutdown subdirectory: %m");
1843 r
= fopen_temporary("/run/systemd/shutdown/scheduled", &f
, &temp_path
);
1845 return log_error_errno(r
, "Failed to save information about scheduled shutdowns: %m");
1847 (void) fchmod(fileno(f
), 0644);
1853 m
->scheduled_shutdown_timeout
,
1854 m
->enable_wall_messages
,
1855 m
->scheduled_shutdown_type
);
1857 if (!isempty(m
->wall_message
)) {
1858 _cleanup_free_
char *t
;
1860 t
= cescape(m
->wall_message
);
1866 fprintf(f
, "WALL_MESSAGE=%s\n", t
);
1869 r
= fflush_and_check(f
);
1873 if (rename(temp_path
, "/run/systemd/shutdown/scheduled") < 0) {
1881 (void) unlink(temp_path
);
1882 (void) unlink("/run/systemd/shutdown/scheduled");
1884 return log_error_errno(r
, "Failed to write information about scheduled shutdowns: %m");
1887 static int manager_scheduled_shutdown_handler(
1892 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1893 Manager
*m
= userdata
;
1899 if (isempty(m
->scheduled_shutdown_type
))
1902 if (streq(m
->scheduled_shutdown_type
, "halt"))
1903 target
= SPECIAL_HALT_TARGET
;
1904 else if (streq(m
->scheduled_shutdown_type
, "poweroff"))
1905 target
= SPECIAL_POWEROFF_TARGET
;
1907 target
= SPECIAL_REBOOT_TARGET
;
1909 r
= execute_shutdown_or_sleep(m
, 0, target
, &error
);
1911 return log_error_errno(r
, "Unable to execute transition to %s: %m", target
);
1916 static int method_schedule_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1917 Manager
*m
= userdata
;
1918 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1919 const char *action_multiple_sessions
= NULL
;
1920 const char *action_ignore_inhibit
= NULL
;
1921 const char *action
= NULL
;
1929 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
1933 if (startswith(type
, "dry-")) {
1935 m
->shutdown_dry_run
= true;
1938 if (streq(type
, "reboot")) {
1939 action
= "org.freedesktop.login1.reboot";
1940 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
1941 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
1942 } else if (streq(type
, "halt")) {
1943 action
= "org.freedesktop.login1.halt";
1944 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
1945 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
1946 } else if (streq(type
, "poweroff")) {
1947 action
= "org.freedesktop.login1.poweroff";
1948 action_multiple_sessions
= "org.freedesktop.login1.poweroff-multiple-sessions";
1949 action_ignore_inhibit
= "org.freedesktop.login1.poweroff-ignore-inhibit";
1951 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
1953 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
1954 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
1958 if (m
->scheduled_shutdown_timeout_source
) {
1959 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
1961 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1963 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
1965 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1967 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
1968 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
1970 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1973 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
1975 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1979 if (m
->nologin_timeout_source
) {
1980 r
= sd_event_source_set_time(m
->nologin_timeout_source
, elapse
);
1982 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1984 r
= sd_event_source_set_enabled(m
->nologin_timeout_source
, SD_EVENT_ONESHOT
);
1986 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1988 r
= sd_event_add_time(m
->event
, &m
->nologin_timeout_source
,
1989 CLOCK_REALTIME
, elapse
- 5 * USEC_PER_MINUTE
, 0, nologin_timeout_handler
, m
);
1991 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1994 m
->scheduled_shutdown_timeout
= elapse
;
1996 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2000 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
2001 (void) sd_bus_creds_get_tty(creds
, &tty
);
2003 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
2005 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2010 r
= manager_setup_wall_message_timer(m
);
2014 if (!isempty(type
)) {
2015 r
= update_schedule_file(m
);
2019 (void) unlink("/run/systemd/shutdown/scheduled");
2021 return sd_bus_reply_method_return(message
, NULL
);
2024 static int method_cancel_scheduled_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2025 Manager
*m
= userdata
;
2031 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
2032 reset_scheduled_shutdown(m
);
2035 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2036 const char *tty
= NULL
;
2040 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2042 (void) sd_bus_creds_get_uid(creds
, &uid
);
2043 (void) sd_bus_creds_get_tty(creds
, &tty
);
2046 utmp_wall("The system shutdown has been cancelled",
2047 uid_to_name(uid
), tty
, logind_wall_tty_filter
, m
);
2050 return sd_bus_reply_method_return(message
, "b", cancelled
);
2053 static int method_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2054 Manager
*m
= userdata
;
2056 return method_do_shutdown_or_sleep(
2058 SPECIAL_HIBERNATE_TARGET
,
2060 "org.freedesktop.login1.hibernate",
2061 "org.freedesktop.login1.hibernate-multiple-sessions",
2062 "org.freedesktop.login1.hibernate-ignore-inhibit",
2067 static int method_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2068 Manager
*m
= userdata
;
2070 return method_do_shutdown_or_sleep(
2072 SPECIAL_HYBRID_SLEEP_TARGET
,
2074 "org.freedesktop.login1.hibernate",
2075 "org.freedesktop.login1.hibernate-multiple-sessions",
2076 "org.freedesktop.login1.hibernate-ignore-inhibit",
2081 static int method_can_shutdown_or_sleep(
2083 sd_bus_message
*message
,
2086 const char *action_multiple_sessions
,
2087 const char *action_ignore_inhibit
,
2088 const char *sleep_verb
,
2089 sd_bus_error
*error
) {
2091 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2092 bool multiple_sessions
, challenge
, blocked
;
2093 const char *result
= NULL
;
2100 assert(w
<= _INHIBIT_WHAT_MAX
);
2102 assert(action_multiple_sessions
);
2103 assert(action_ignore_inhibit
);
2106 r
= can_sleep(sleep_verb
);
2110 return sd_bus_reply_method_return(message
, "s", "na");
2113 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
2117 r
= sd_bus_creds_get_euid(creds
, &uid
);
2121 r
= have_multiple_sessions(m
, uid
);
2125 multiple_sessions
= r
> 0;
2126 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
2128 if (multiple_sessions
) {
2129 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, UID_INVALID
, &challenge
, error
);
2136 result
= "challenge";
2142 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, UID_INVALID
, &challenge
, error
);
2146 if (r
> 0 && !result
)
2148 else if (challenge
&& (!result
|| streq(result
, "yes")))
2149 result
= "challenge";
2154 if (!multiple_sessions
&& !blocked
) {
2155 /* If neither inhibit nor multiple sessions
2156 * apply then just check the normal policy */
2158 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, NULL
, UID_INVALID
, &challenge
, error
);
2165 result
= "challenge";
2170 return sd_bus_reply_method_return(message
, "s", result
);
2173 static int method_can_poweroff(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.power-off",
2180 "org.freedesktop.login1.power-off-multiple-sessions",
2181 "org.freedesktop.login1.power-off-ignore-inhibit",
2186 static int method_can_reboot(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.reboot",
2193 "org.freedesktop.login1.reboot-multiple-sessions",
2194 "org.freedesktop.login1.reboot-ignore-inhibit",
2199 static int method_can_suspend(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.suspend",
2206 "org.freedesktop.login1.suspend-multiple-sessions",
2207 "org.freedesktop.login1.suspend-ignore-inhibit",
2212 static int method_can_hibernate(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 method_can_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2226 Manager
*m
= userdata
;
2228 return method_can_shutdown_or_sleep(
2231 "org.freedesktop.login1.hibernate",
2232 "org.freedesktop.login1.hibernate-multiple-sessions",
2233 "org.freedesktop.login1.hibernate-ignore-inhibit",
2238 static int property_get_reboot_to_firmware_setup(
2241 const char *interface
,
2242 const char *property
,
2243 sd_bus_message
*reply
,
2245 sd_bus_error
*error
) {
2252 r
= efi_get_reboot_to_firmware();
2253 if (r
< 0 && r
!= -EOPNOTSUPP
)
2256 return sd_bus_message_append(reply
, "b", r
> 0);
2259 static int method_set_reboot_to_firmware_setup(
2260 sd_bus_message
*message
,
2262 sd_bus_error
*error
) {
2265 Manager
*m
= userdata
;
2270 r
= sd_bus_message_read(message
, "b", &b
);
2274 r
= bus_verify_polkit_async(message
,
2276 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2280 &m
->polkit_registry
,
2285 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2287 r
= efi_set_reboot_to_firmware(b
);
2291 return sd_bus_reply_method_return(message
, NULL
);
2294 static int method_can_reboot_to_firmware_setup(
2295 sd_bus_message
*message
,
2297 sd_bus_error
*error
) {
2302 Manager
*m
= userdata
;
2307 r
= efi_reboot_to_firmware_supported();
2308 if (r
== -EOPNOTSUPP
)
2309 return sd_bus_reply_method_return(message
, "s", "na");
2313 r
= bus_test_polkit(message
,
2315 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2326 result
= "challenge";
2330 return sd_bus_reply_method_return(message
, "s", result
);
2333 static int method_set_wall_message(
2334 sd_bus_message
*message
,
2336 sd_bus_error
*error
) {
2339 Manager
*m
= userdata
;
2341 int enable_wall_messages
;
2346 r
= sd_bus_message_read(message
, "sb", &wall_message
, &enable_wall_messages
);
2350 r
= bus_verify_polkit_async(message
,
2352 "org.freedesktop.login1.set-wall-message",
2356 &m
->polkit_registry
,
2361 return 1; /* Will call us back */
2363 if (isempty(wall_message
))
2364 m
->wall_message
= mfree(m
->wall_message
);
2366 r
= free_and_strdup(&m
->wall_message
, wall_message
);
2371 m
->enable_wall_messages
= enable_wall_messages
;
2373 return sd_bus_reply_method_return(message
, NULL
);
2376 static int method_inhibit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2377 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2378 const char *who
, *why
, *what
, *mode
;
2379 _cleanup_free_
char *id
= NULL
;
2380 _cleanup_close_
int fifo_fd
= -1;
2381 Manager
*m
= userdata
;
2382 Inhibitor
*i
= NULL
;
2392 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2396 w
= inhibit_what_from_string(what
);
2398 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2400 mm
= inhibit_mode_from_string(mode
);
2402 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2404 /* Delay is only supported for shutdown/sleep */
2405 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2406 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2408 /* Don't allow taking delay locks while we are already
2409 * executing the operation. We shouldn't create the impression
2410 * that the lock was successful if the machine is about to go
2411 * down/suspend any moment. */
2412 if (m
->action_what
& w
)
2413 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2415 r
= bus_verify_polkit_async(
2418 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2419 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2420 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2421 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2422 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2423 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2424 "org.freedesktop.login1.inhibit-handle-lid-switch",
2428 &m
->polkit_registry
,
2433 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2435 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2439 r
= sd_bus_creds_get_euid(creds
, &uid
);
2443 r
= sd_bus_creds_get_pid(creds
, &pid
);
2450 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2453 } while (hashmap_get(m
->inhibitors
, id
));
2455 r
= manager_add_inhibitor(m
, id
, &i
);
2463 i
->why
= strdup(why
);
2464 i
->who
= strdup(who
);
2466 if (!i
->why
|| !i
->who
) {
2471 fifo_fd
= inhibitor_create_fifo(i
);
2479 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2488 const sd_bus_vtable manager_vtable
[] = {
2489 SD_BUS_VTABLE_START(0),
2491 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2492 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2494 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2495 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2496 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2497 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2498 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2499 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2500 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2501 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2502 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2503 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2504 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2505 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2506 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2507 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2508 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2509 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2510 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2511 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2512 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2513 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2514 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2515 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2516 SD_BUS_PROPERTY("Docked", "b", property_get_docked
, 0, 0),
2518 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2519 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2520 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2521 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2522 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2523 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2524 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2525 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2526 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2527 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2528 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2529 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2530 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2531 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2532 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2533 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2534 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2535 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2536 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2537 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2538 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2539 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2540 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2541 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2542 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2543 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2544 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2545 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2546 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2547 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2548 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2549 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2550 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2551 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2552 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2553 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2554 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2555 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2556 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2557 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2558 SD_BUS_METHOD("SetWallMessage", "sb", NULL
, method_set_wall_message
, SD_BUS_VTABLE_UNPRIVILEGED
),
2560 SD_BUS_SIGNAL("SessionNew", "so", 0),
2561 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2562 SD_BUS_SIGNAL("UserNew", "uo", 0),
2563 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2564 SD_BUS_SIGNAL("SeatNew", "so", 0),
2565 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2566 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2567 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2572 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2581 if (streq(result
, "done"))
2582 r
= session_send_create_reply(s
, NULL
);
2584 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
2586 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2587 r
= session_send_create_reply(s
, &e
);
2593 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2594 const char *path
, *result
, *unit
;
2595 Manager
*m
= userdata
;
2604 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2606 bus_log_parse_error(r
);
2610 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2611 log_info("Operation '%s' finished.", inhibit_what_to_string(m
->action_what
));
2613 /* Tell people that they now may take a lock again */
2614 send_prepare_for(m
, m
->action_what
, false);
2616 m
->action_job
= mfree(m
->action_job
);
2617 m
->action_unit
= NULL
;
2622 session
= hashmap_get(m
->session_units
, unit
);
2623 if (session
&& streq_ptr(path
, session
->scope_job
)) {
2624 session
->scope_job
= mfree(session
->scope_job
);
2625 session_jobs_reply(session
, unit
, result
);
2627 session_save(session
);
2628 user_save(session
->user
);
2629 session_add_to_gc_queue(session
);
2632 user
= hashmap_get(m
->user_units
, unit
);
2634 (streq_ptr(path
, user
->service_job
) ||
2635 streq_ptr(path
, user
->slice_job
))) {
2637 if (streq_ptr(path
, user
->service_job
))
2638 user
->service_job
= mfree(user
->service_job
);
2640 if (streq_ptr(path
, user
->slice_job
))
2641 user
->slice_job
= mfree(user
->slice_job
);
2643 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
)
2644 session_jobs_reply(session
, unit
, result
);
2647 user_add_to_gc_queue(user
);
2653 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2654 const char *path
, *unit
;
2655 Manager
*m
= userdata
;
2663 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2665 bus_log_parse_error(r
);
2669 session
= hashmap_get(m
->session_units
, unit
);
2671 session_add_to_gc_queue(session
);
2673 user
= hashmap_get(m
->user_units
, unit
);
2675 user_add_to_gc_queue(user
);
2680 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2681 _cleanup_free_
char *unit
= NULL
;
2682 Manager
*m
= userdata
;
2691 path
= sd_bus_message_get_path(message
);
2695 r
= unit_name_from_dbus_path(path
, &unit
);
2696 if (r
== -EINVAL
) /* not a unit */
2703 session
= hashmap_get(m
->session_units
, unit
);
2705 session_add_to_gc_queue(session
);
2707 user
= hashmap_get(m
->user_units
, unit
);
2709 user_add_to_gc_queue(user
);
2714 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2715 Manager
*m
= userdata
;
2723 r
= sd_bus_message_read(message
, "b", &b
);
2725 bus_log_parse_error(r
);
2732 /* systemd finished reloading, let's recheck all our sessions */
2733 log_debug("System manager has been reloaded, rechecking sessions...");
2735 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2736 session_add_to_gc_queue(session
);
2741 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2746 l
= strv_from_stdarg_alloca(property
);
2748 return sd_bus_emit_properties_changed_strv(
2750 "/org/freedesktop/login1",
2751 "org.freedesktop.login1.Manager",
2755 int manager_start_slice(
2758 const char *description
,
2762 sd_bus_error
*error
,
2765 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
2771 r
= sd_bus_message_new_method_call(
2774 "org.freedesktop.systemd1",
2775 "/org/freedesktop/systemd1",
2776 "org.freedesktop.systemd1.Manager",
2777 "StartTransientUnit");
2781 r
= sd_bus_message_append(m
, "ss", strempty(slice
), "fail");
2785 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2789 if (!isempty(description
)) {
2790 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2795 if (!isempty(after
)) {
2796 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2801 if (!isempty(after2
)) {
2802 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2807 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
2811 r
= sd_bus_message_close_container(m
);
2815 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2819 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2827 r
= sd_bus_message_read(reply
, "o", &j
);
2841 int manager_start_scope(
2846 const char *description
,
2850 sd_bus_error
*error
,
2853 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
2860 r
= sd_bus_message_new_method_call(
2863 "org.freedesktop.systemd1",
2864 "/org/freedesktop/systemd1",
2865 "org.freedesktop.systemd1.Manager",
2866 "StartTransientUnit");
2870 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
2874 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2878 if (!isempty(slice
)) {
2879 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
2884 if (!isempty(description
)) {
2885 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2890 if (!isempty(after
)) {
2891 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2896 if (!isempty(after2
)) {
2897 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2902 /* cgroup empty notification is not available in containers
2903 * currently. To make this less problematic, let's shorten the
2904 * stop timeout for sessions, so that we don't wait
2907 /* Make sure that the session shells are terminated with
2908 * SIGHUP since bash and friends tend to ignore SIGTERM */
2909 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
2913 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
2917 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
2921 r
= sd_bus_message_close_container(m
);
2925 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2929 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2937 r
= sd_bus_message_read(reply
, "o", &j
);
2951 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2952 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2958 r
= sd_bus_call_method(
2960 "org.freedesktop.systemd1",
2961 "/org/freedesktop/systemd1",
2962 "org.freedesktop.systemd1.Manager",
2966 "ss", unit
, "replace");
2974 r
= sd_bus_message_read(reply
, "o", &j
);
2988 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2989 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2995 r
= sd_bus_call_method(
2997 "org.freedesktop.systemd1",
2998 "/org/freedesktop/systemd1",
2999 "org.freedesktop.systemd1.Manager",
3003 "ss", unit
, "fail");
3005 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3006 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
3011 sd_bus_error_free(error
);
3022 r
= sd_bus_message_read(reply
, "o", &j
);
3036 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
3037 _cleanup_free_
char *path
= NULL
;
3043 path
= unit_dbus_path_from_name(scope
);
3047 r
= sd_bus_call_method(
3049 "org.freedesktop.systemd1",
3051 "org.freedesktop.systemd1.Scope",
3057 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3058 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
3059 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
3060 sd_bus_error_free(error
);
3070 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
3074 return sd_bus_call_method(
3076 "org.freedesktop.systemd1",
3077 "/org/freedesktop/systemd1",
3078 "org.freedesktop.systemd1.Manager",
3082 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
3085 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
3086 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3087 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
3088 _cleanup_free_
char *path
= NULL
;
3095 path
= unit_dbus_path_from_name(unit
);
3099 r
= sd_bus_get_property(
3101 "org.freedesktop.systemd1",
3103 "org.freedesktop.systemd1.Unit",
3109 /* systemd might have droppped off momentarily, let's
3110 * not make this an error */
3111 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3112 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3115 /* If the unit is already unloaded then it's not
3117 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3118 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
3124 r
= sd_bus_message_read(reply
, "s", &state
);
3128 return !streq(state
, "inactive") && !streq(state
, "failed");
3131 int manager_job_is_active(Manager
*manager
, const char *path
) {
3132 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
3133 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
3139 r
= sd_bus_get_property(
3141 "org.freedesktop.systemd1",
3143 "org.freedesktop.systemd1.Job",
3149 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3150 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3153 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
3159 /* We don't actually care about the state really. The fact
3160 * that we could read the job state is enough for us */