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_(sd_bus_creds_unrefp
) 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_(sd_bus_creds_unrefp
) 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
;
128 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "Session has no seat.");
130 seat
= hashmap_get(m
->seats
, name
);
132 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", name
);
139 static int property_get_idle_hint(
142 const char *interface
,
143 const char *property
,
144 sd_bus_message
*reply
,
146 sd_bus_error
*error
) {
148 Manager
*m
= userdata
;
154 return sd_bus_message_append(reply
, "b", manager_get_idle_hint(m
, NULL
) > 0);
157 static int property_get_idle_since_hint(
160 const char *interface
,
161 const char *property
,
162 sd_bus_message
*reply
,
164 sd_bus_error
*error
) {
166 Manager
*m
= userdata
;
167 dual_timestamp t
= DUAL_TIMESTAMP_NULL
;
173 manager_get_idle_hint(m
, &t
);
175 return sd_bus_message_append(reply
, "t", streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
);
178 static int property_get_inhibited(
181 const char *interface
,
182 const char *property
,
183 sd_bus_message
*reply
,
185 sd_bus_error
*error
) {
187 Manager
*m
= userdata
;
194 w
= manager_inhibit_what(m
, streq(property
, "BlockInhibited") ? INHIBIT_BLOCK
: INHIBIT_DELAY
);
196 return sd_bus_message_append(reply
, "s", inhibit_what_to_string(w
));
199 static int property_get_preparing(
202 const char *interface
,
203 const char *property
,
204 sd_bus_message
*reply
,
206 sd_bus_error
*error
) {
208 Manager
*m
= userdata
;
215 if (streq(property
, "PreparingForShutdown"))
216 b
= !!(m
->action_what
& INHIBIT_SHUTDOWN
);
218 b
= !!(m
->action_what
& INHIBIT_SLEEP
);
220 return sd_bus_message_append(reply
, "b", b
);
223 static int property_get_scheduled_shutdown(
226 const char *interface
,
227 const char *property
,
228 sd_bus_message
*reply
,
230 sd_bus_error
*error
) {
232 Manager
*m
= userdata
;
239 r
= sd_bus_message_open_container(reply
, 'r', "st");
243 r
= sd_bus_message_append(reply
, "st", m
->scheduled_shutdown_type
, m
->scheduled_shutdown_timeout
);
247 return sd_bus_message_close_container(reply
);
250 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action
, handle_action
, HandleAction
);
252 static int property_get_docked(
255 const char *interface
,
256 const char *property
,
257 sd_bus_message
*reply
,
259 sd_bus_error
*error
) {
261 Manager
*m
= userdata
;
267 return sd_bus_message_append(reply
, "b", manager_is_docked_or_external_displays(m
));
270 static int method_get_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
271 _cleanup_free_
char *p
= NULL
;
272 Manager
*m
= userdata
;
280 r
= sd_bus_message_read(message
, "s", &name
);
284 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
288 p
= session_bus_path(session
);
292 return sd_bus_reply_method_return(message
, "o", p
);
295 static int method_get_session_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
296 _cleanup_free_
char *p
= NULL
;
297 Session
*session
= NULL
;
298 Manager
*m
= userdata
;
305 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
307 r
= sd_bus_message_read(message
, "u", &pid
);
314 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
318 r
= manager_get_session_by_pid(m
, pid
, &session
);
323 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
326 p
= session_bus_path(session
);
330 return sd_bus_reply_method_return(message
, "o", p
);
333 static int method_get_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
334 _cleanup_free_
char *p
= NULL
;
335 Manager
*m
= userdata
;
343 r
= sd_bus_message_read(message
, "u", &uid
);
347 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
351 p
= user_bus_path(user
);
355 return sd_bus_reply_method_return(message
, "o", p
);
358 static int method_get_user_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
359 _cleanup_free_
char *p
= NULL
;
360 Manager
*m
= userdata
;
368 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
370 r
= sd_bus_message_read(message
, "u", &pid
);
377 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
381 r
= manager_get_user_by_pid(m
, pid
, &user
);
385 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
);
388 p
= user_bus_path(user
);
392 return sd_bus_reply_method_return(message
, "o", p
);
395 static int method_get_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
396 _cleanup_free_
char *p
= NULL
;
397 Manager
*m
= userdata
;
405 r
= sd_bus_message_read(message
, "s", &name
);
409 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
413 p
= seat_bus_path(seat
);
417 return sd_bus_reply_method_return(message
, "o", p
);
420 static int method_list_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
421 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
422 Manager
*m
= userdata
;
430 r
= sd_bus_message_new_method_return(message
, &reply
);
434 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
438 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
439 _cleanup_free_
char *p
= NULL
;
441 p
= session_bus_path(session
);
445 r
= sd_bus_message_append(reply
, "(susso)",
447 (uint32_t) session
->user
->uid
,
449 session
->seat
? session
->seat
->id
: "",
455 r
= sd_bus_message_close_container(reply
);
459 return sd_bus_send(NULL
, reply
, NULL
);
462 static int method_list_users(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
463 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
464 Manager
*m
= userdata
;
472 r
= sd_bus_message_new_method_return(message
, &reply
);
476 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
480 HASHMAP_FOREACH(user
, m
->users
, i
) {
481 _cleanup_free_
char *p
= NULL
;
483 p
= user_bus_path(user
);
487 r
= sd_bus_message_append(reply
, "(uso)",
488 (uint32_t) user
->uid
,
495 r
= sd_bus_message_close_container(reply
);
499 return sd_bus_send(NULL
, reply
, NULL
);
502 static int method_list_seats(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
503 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
504 Manager
*m
= userdata
;
512 r
= sd_bus_message_new_method_return(message
, &reply
);
516 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
520 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
521 _cleanup_free_
char *p
= NULL
;
523 p
= seat_bus_path(seat
);
527 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
532 r
= sd_bus_message_close_container(reply
);
536 return sd_bus_send(NULL
, reply
, NULL
);
539 static int method_list_inhibitors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
540 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
541 Manager
*m
= userdata
;
542 Inhibitor
*inhibitor
;
549 r
= sd_bus_message_new_method_return(message
, &reply
);
553 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
557 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
559 r
= sd_bus_message_append(reply
, "(ssssuu)",
560 strempty(inhibit_what_to_string(inhibitor
->what
)),
561 strempty(inhibitor
->who
),
562 strempty(inhibitor
->why
),
563 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
564 (uint32_t) inhibitor
->uid
,
565 (uint32_t) inhibitor
->pid
);
570 r
= sd_bus_message_close_container(reply
);
574 return sd_bus_send(NULL
, reply
, NULL
);
577 static int method_create_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
578 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
579 uint32_t audit_id
= 0;
580 _cleanup_free_
char *id
= NULL
;
581 Session
*session
= NULL
;
582 Manager
*m
= userdata
;
596 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
597 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
599 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
603 if (!uid_is_valid(uid
))
604 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid UID");
605 if (leader
< 0 || leader
== 1)
606 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
609 t
= _SESSION_TYPE_INVALID
;
611 t
= session_type_from_string(type
);
613 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
617 c
= _SESSION_CLASS_INVALID
;
619 c
= session_class_from_string(class);
621 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
624 if (isempty(desktop
))
627 if (!string_is_safe(desktop
))
628 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
634 seat
= hashmap_get(m
->seats
, cseat
);
636 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
639 if (tty_is_vc(tty
)) {
644 else if (seat
!= m
->seat0
)
645 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
);
647 v
= vtnr_from_tty(tty
);
649 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
653 else if (vtnr
!= (uint32_t) v
)
654 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
656 } else if (tty_is_console(tty
)) {
660 else if (seat
!= m
->seat0
)
661 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
664 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
668 if (seat_has_vts(seat
)) {
669 if (!vtnr
|| vtnr
> 63)
670 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
673 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
677 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
681 if (t
== _SESSION_TYPE_INVALID
) {
682 if (!isempty(display
))
684 else if (!isempty(tty
))
687 t
= SESSION_UNSPECIFIED
;
690 if (c
== _SESSION_CLASS_INVALID
) {
691 if (t
== SESSION_UNSPECIFIED
)
692 c
= SESSION_BACKGROUND
;
698 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
700 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
704 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
709 r
= manager_get_session_by_pid(m
, leader
, NULL
);
711 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already running in a session");
714 * Old gdm and lightdm start the user-session on the same VT as
715 * the greeter session. But they destroy the greeter session
716 * after the user-session and want the user-session to take
717 * over the VT. We need to support this for
718 * backwards-compatibility, so make sure we allow new sessions
719 * on a VT that a greeter is running on. Furthermore, to allow
720 * re-logins, we have to allow a greeter to take over a used VT for
721 * the exact same reasons.
723 if (c
!= SESSION_GREETER
&&
725 vtnr
< m
->seat0
->position_count
&&
726 m
->seat0
->positions
[vtnr
] &&
727 m
->seat0
->positions
[vtnr
]->class != SESSION_GREETER
)
728 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_BUSY
, "Already occupied by a session");
730 audit_session_from_pid(leader
, &audit_id
);
732 /* Keep our session IDs and the audit session IDs in sync */
734 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
737 /* Wut? There's already a session by this name and we
738 * didn't find it above? Weird, then let's not trust
739 * the audit data and let's better register a new
741 if (hashmap_get(m
->sessions
, id
)) {
742 log_warning("Existing logind session ID %s used by new audit session, ignoring", id
);
753 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
756 } while (hashmap_get(m
->sessions
, id
));
759 r
= manager_add_user_by_uid(m
, uid
, &user
);
763 r
= manager_add_session(m
, id
, &session
);
767 session_set_user(session
, user
);
769 session
->leader
= leader
;
770 session
->audit_id
= audit_id
;
773 session
->remote
= remote
;
774 session
->vtnr
= vtnr
;
777 session
->tty
= strdup(tty
);
784 if (!isempty(display
)) {
785 session
->display
= strdup(display
);
786 if (!session
->display
) {
792 if (!isempty(remote_user
)) {
793 session
->remote_user
= strdup(remote_user
);
794 if (!session
->remote_user
) {
800 if (!isempty(remote_host
)) {
801 session
->remote_host
= strdup(remote_host
);
802 if (!session
->remote_host
) {
808 if (!isempty(service
)) {
809 session
->service
= strdup(service
);
810 if (!session
->service
) {
816 if (!isempty(desktop
)) {
817 session
->desktop
= strdup(desktop
);
818 if (!session
->desktop
) {
825 r
= seat_attach_session(seat
, session
);
830 r
= session_start(session
);
834 session
->create_message
= sd_bus_message_ref(message
);
836 /* Now, let's wait until the slice unit and stuff got
837 * created. We send the reply back from
838 * session_send_create_reply(). */
844 session_add_to_gc_queue(session
);
847 user_add_to_gc_queue(user
);
852 static int method_release_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
853 Manager
*m
= userdata
;
861 r
= sd_bus_message_read(message
, "s", &name
);
865 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
869 r
= session_release(session
);
873 return sd_bus_reply_method_return(message
, NULL
);
876 static int method_activate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
877 Manager
*m
= userdata
;
885 r
= sd_bus_message_read(message
, "s", &name
);
889 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
893 return bus_session_method_activate(message
, session
, error
);
896 static int method_activate_session_on_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
897 const char *session_name
, *seat_name
;
898 Manager
*m
= userdata
;
906 /* Same as ActivateSession() but refuses to work if
907 * the seat doesn't match */
909 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
913 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
917 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
921 if (session
->seat
!= seat
)
922 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
924 r
= session_activate(session
);
928 return sd_bus_reply_method_return(message
, NULL
);
931 static int method_lock_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
932 Manager
*m
= userdata
;
940 r
= sd_bus_message_read(message
, "s", &name
);
944 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
948 return bus_session_method_lock(message
, session
, error
);
951 static int method_lock_sessions(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
952 Manager
*m
= userdata
;
958 r
= bus_verify_polkit_async(
961 "org.freedesktop.login1.lock-sessions",
970 return 1; /* Will call us back */
972 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
976 return sd_bus_reply_method_return(message
, NULL
);
979 static int method_kill_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
981 Manager
*m
= userdata
;
988 r
= sd_bus_message_read(message
, "s", &name
);
992 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
996 return bus_session_method_kill(message
, session
, error
);
999 static int method_kill_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1000 Manager
*m
= userdata
;
1008 r
= sd_bus_message_read(message
, "u", &uid
);
1012 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1016 return bus_user_method_kill(message
, user
, error
);
1019 static int method_terminate_session(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1020 Manager
*m
= userdata
;
1028 r
= sd_bus_message_read(message
, "s", &name
);
1032 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1036 return bus_session_method_terminate(message
, session
, error
);
1039 static int method_terminate_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1040 Manager
*m
= userdata
;
1048 r
= sd_bus_message_read(message
, "u", &uid
);
1052 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1056 return bus_user_method_terminate(message
, user
, error
);
1059 static int method_terminate_seat(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1060 Manager
*m
= userdata
;
1068 r
= sd_bus_message_read(message
, "s", &name
);
1072 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
1076 return bus_seat_method_terminate(message
, seat
, error
);
1079 static int method_set_user_linger(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1080 _cleanup_free_
char *cc
= NULL
;
1081 Manager
*m
= userdata
;
1091 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1095 if (uid
== UID_INVALID
) {
1096 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1098 /* Note that we get the owner UID of the session, not the actual client UID here! */
1099 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1103 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1107 } else if (!uid_is_valid(uid
))
1113 return errno
> 0 ? -errno
: -ENOENT
;
1115 r
= bus_verify_polkit_async(
1118 "org.freedesktop.login1.set-user-linger",
1122 &m
->polkit_registry
,
1127 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1129 mkdir_p_label("/var/lib/systemd", 0755);
1131 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1135 cc
= cescape(pw
->pw_name
);
1139 path
= strjoina("/var/lib/systemd/linger/", cc
);
1147 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1154 if (r
< 0 && errno
!= ENOENT
)
1157 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1159 user_add_to_gc_queue(u
);
1162 return sd_bus_reply_method_return(message
, NULL
);
1165 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1166 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1167 struct udev_list_entry
*first
, *item
;
1172 e
= udev_enumerate_new(m
->udev
);
1177 r
= udev_enumerate_add_match_parent(e
, d
);
1182 r
= udev_enumerate_scan_devices(e
);
1186 first
= udev_enumerate_get_list_entry(e
);
1187 udev_list_entry_foreach(item
, first
) {
1188 _cleanup_free_
char *t
= NULL
;
1191 p
= udev_list_entry_get_name(item
);
1193 t
= strappend(p
, "/uevent");
1197 write_string_file(t
, "change", WRITE_STRING_FILE_CREATE
);
1203 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1204 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1205 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1206 const char *id_for_seat
;
1213 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1217 if (!udev_device_has_tag(d
, "seat"))
1220 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1224 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1227 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1230 mkdir_p_label("/etc/udev/rules.d", 0755);
1231 mac_selinux_init("/etc");
1232 r
= write_string_file_atomic_label(file
, rule
);
1236 return trigger_device(m
, d
);
1239 static int flush_devices(Manager
*m
) {
1240 _cleanup_closedir_
DIR *d
;
1244 d
= opendir("/etc/udev/rules.d");
1246 if (errno
!= ENOENT
)
1247 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1251 while ((de
= readdir(d
))) {
1253 if (!dirent_is_file(de
))
1256 if (!startswith(de
->d_name
, "72-seat-"))
1259 if (!endswith(de
->d_name
, ".rules"))
1262 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1263 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1267 return trigger_device(m
, NULL
);
1270 static int method_attach_device(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1271 const char *sysfs
, *seat
;
1272 Manager
*m
= userdata
;
1278 r
= sd_bus_message_read(message
, "ssb", &seat
, &sysfs
, &interactive
);
1282 if (!path_startswith(sysfs
, "/sys"))
1283 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not in /sys", sysfs
);
1285 if (!seat_name_is_valid(seat
))
1286 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat %s is not valid", seat
);
1288 r
= bus_verify_polkit_async(
1291 "org.freedesktop.login1.attach-device",
1295 &m
->polkit_registry
,
1300 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1302 r
= attach_device(m
, seat
, sysfs
);
1306 return sd_bus_reply_method_return(message
, NULL
);
1309 static int method_flush_devices(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1310 Manager
*m
= userdata
;
1316 r
= sd_bus_message_read(message
, "b", &interactive
);
1320 r
= bus_verify_polkit_async(
1323 "org.freedesktop.login1.flush-devices",
1327 &m
->polkit_registry
,
1332 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1334 r
= flush_devices(m
);
1338 return sd_bus_reply_method_return(message
, NULL
);
1341 static int have_multiple_sessions(
1350 /* Check for other users' sessions. Greeter sessions do not
1351 * count, and non-login sessions do not count either. */
1352 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1353 if (session
->class == SESSION_USER
&&
1354 session
->user
->uid
!= uid
)
1360 static int bus_manager_log_shutdown(
1363 const char *unit_name
) {
1370 if (w
!= INHIBIT_SHUTDOWN
)
1373 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1374 p
= "MESSAGE=System is powering down";
1375 q
= "SHUTDOWN=power-off";
1376 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1377 p
= "MESSAGE=System is halting";
1378 q
= "SHUTDOWN=halt";
1379 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1380 p
= "MESSAGE=System is rebooting";
1381 q
= "SHUTDOWN=reboot";
1382 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1383 p
= "MESSAGE=System is rebooting with kexec";
1384 q
= "SHUTDOWN=kexec";
1386 p
= "MESSAGE=System is shutting down";
1390 if (isempty(m
->wall_message
))
1391 p
= strjoina(p
, ".");
1393 p
= strjoina(p
, " (", m
->wall_message
, ").");
1395 return log_struct(LOG_NOTICE
,
1396 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN
),
1402 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1403 Manager
*m
= userdata
;
1408 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1412 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1417 if (until
<= now(CLOCK_MONOTONIC
))
1420 /* We want to ignore the lid switch for a while after each
1421 * suspend, and after boot-up. Hence let's install a timer for
1422 * this. As long as the event source exists we ignore the lid
1425 if (m
->lid_switch_ignore_event_source
) {
1428 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1435 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1437 r
= sd_event_add_time(
1439 &m
->lid_switch_ignore_event_source
,
1442 lid_switch_ignore_handler
, m
);
1447 static void reset_scheduled_shutdown(Manager
*m
) {
1448 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1449 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
1450 m
->nologin_timeout_source
= sd_event_source_unref(m
->nologin_timeout_source
);
1451 m
->scheduled_shutdown_type
= mfree(m
->scheduled_shutdown_type
);
1452 m
->scheduled_shutdown_timeout
= 0;
1453 m
->shutdown_dry_run
= false;
1455 if (m
->unlink_nologin
) {
1456 (void) unlink("/run/nologin");
1457 m
->unlink_nologin
= false;
1461 static int execute_shutdown_or_sleep(
1464 const char *unit_name
,
1465 sd_bus_error
*error
) {
1467 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1474 assert(w
< _INHIBIT_WHAT_MAX
);
1477 bus_manager_log_shutdown(m
, w
, unit_name
);
1479 if (m
->shutdown_dry_run
) {
1480 log_info("Running in dry run, suppressing action.");
1481 reset_scheduled_shutdown(m
);
1483 r
= sd_bus_call_method(
1485 "org.freedesktop.systemd1",
1486 "/org/freedesktop/systemd1",
1487 "org.freedesktop.systemd1.Manager",
1491 "ss", unit_name
, "replace-irreversibly");
1495 r
= sd_bus_message_read(reply
, "o", &p
);
1504 m
->action_unit
= unit_name
;
1505 free(m
->action_job
);
1509 /* Make sure the lid switch is ignored for a while */
1510 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1515 int manager_dispatch_delayed(Manager
*manager
, bool timeout
) {
1517 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1518 Inhibitor
*offending
= NULL
;
1523 if (manager
->action_what
== 0 || manager
->action_job
)
1526 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1527 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1532 (void) get_process_comm(offending
->pid
, &comm
);
1533 u
= uid_to_name(offending
->uid
);
1535 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1536 offending
->uid
, strna(u
),
1537 offending
->pid
, strna(comm
));
1540 /* Actually do the operation */
1541 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1543 log_warning("Failed to send delayed message: %s", bus_error_message(&error
, r
));
1545 manager
->action_unit
= NULL
;
1546 manager
->action_what
= 0;
1553 static int manager_inhibit_timeout_handler(
1558 Manager
*manager
= userdata
;
1562 assert(manager
->inhibit_timeout_source
== s
);
1564 r
= manager_dispatch_delayed(manager
, true);
1565 return (r
< 0) ? r
: 0;
1568 static int delay_shutdown_or_sleep(
1571 const char *unit_name
) {
1578 assert(w
< _INHIBIT_WHAT_MAX
);
1581 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1583 if (m
->inhibit_timeout_source
) {
1584 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1586 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1588 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1590 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1592 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1593 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1598 m
->action_unit
= unit_name
;
1604 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1606 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1607 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1608 [INHIBIT_SLEEP
] = "PrepareForSleep"
1611 int active
= _active
;
1615 assert(w
< _INHIBIT_WHAT_MAX
);
1616 assert(signal_name
[w
]);
1618 return sd_bus_emit_signal(m
->bus
,
1619 "/org/freedesktop/login1",
1620 "org.freedesktop.login1.Manager",
1626 int bus_manager_shutdown_or_sleep_now_or_later(
1628 const char *unit_name
,
1630 sd_bus_error
*error
) {
1638 assert(w
<= _INHIBIT_WHAT_MAX
);
1639 assert(!m
->action_job
);
1641 /* Tell everybody to prepare for shutdown/sleep */
1642 send_prepare_for(m
, w
, true);
1645 m
->inhibit_delay_max
> 0 &&
1646 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1649 /* Shutdown is delayed, keep in mind what we
1650 * want to do, and start a timeout */
1651 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1653 /* Shutdown is not delayed, execute it
1655 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1660 static int verify_shutdown_creds(
1662 sd_bus_message
*message
,
1666 const char *action_multiple_sessions
,
1667 const char *action_ignore_inhibit
,
1668 sd_bus_error
*error
) {
1670 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1671 bool multiple_sessions
, blocked
;
1678 assert(w
<= _INHIBIT_WHAT_MAX
);
1680 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1684 r
= sd_bus_creds_get_euid(creds
, &uid
);
1688 r
= have_multiple_sessions(m
, uid
);
1692 multiple_sessions
= r
> 0;
1693 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1695 if (multiple_sessions
&& action_multiple_sessions
) {
1696 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1700 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1703 if (blocked
&& action_ignore_inhibit
) {
1704 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1708 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1711 if (!multiple_sessions
&& !blocked
&& action
) {
1712 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, NULL
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1716 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1722 static int method_do_shutdown_or_sleep(
1724 sd_bus_message
*message
,
1725 const char *unit_name
,
1728 const char *action_multiple_sessions
,
1729 const char *action_ignore_inhibit
,
1730 const char *sleep_verb
,
1731 sd_bus_error
*error
) {
1739 assert(w
<= _INHIBIT_WHAT_MAX
);
1741 r
= sd_bus_message_read(message
, "b", &interactive
);
1745 /* Don't allow multiple jobs being executed at the same time */
1747 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1750 r
= can_sleep(sleep_verb
);
1755 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1758 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1759 action_ignore_inhibit
, error
);
1763 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1767 return sd_bus_reply_method_return(message
, NULL
);
1770 static int method_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1771 Manager
*m
= userdata
;
1773 return method_do_shutdown_or_sleep(
1775 SPECIAL_POWEROFF_TARGET
,
1777 "org.freedesktop.login1.power-off",
1778 "org.freedesktop.login1.power-off-multiple-sessions",
1779 "org.freedesktop.login1.power-off-ignore-inhibit",
1784 static int method_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1785 Manager
*m
= userdata
;
1787 return method_do_shutdown_or_sleep(
1789 SPECIAL_REBOOT_TARGET
,
1791 "org.freedesktop.login1.reboot",
1792 "org.freedesktop.login1.reboot-multiple-sessions",
1793 "org.freedesktop.login1.reboot-ignore-inhibit",
1798 static int method_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1799 Manager
*m
= userdata
;
1801 return method_do_shutdown_or_sleep(
1803 SPECIAL_SUSPEND_TARGET
,
1805 "org.freedesktop.login1.suspend",
1806 "org.freedesktop.login1.suspend-multiple-sessions",
1807 "org.freedesktop.login1.suspend-ignore-inhibit",
1812 static int nologin_timeout_handler(
1817 Manager
*m
= userdata
;
1820 log_info("Creating /run/nologin, blocking further logins...");
1822 r
= write_string_file_atomic_label("/run/nologin", "System is going down.");
1824 log_error_errno(r
, "Failed to create /run/nologin: %m");
1826 m
->unlink_nologin
= true;
1831 static int update_schedule_file(Manager
*m
) {
1832 _cleanup_free_
char *temp_path
= NULL
;
1833 _cleanup_fclose_
FILE *f
= NULL
;
1838 r
= mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1840 return log_error_errno(r
, "Failed to create shutdown subdirectory: %m");
1842 r
= fopen_temporary("/run/systemd/shutdown/scheduled", &f
, &temp_path
);
1844 return log_error_errno(r
, "Failed to save information about scheduled shutdowns: %m");
1846 (void) fchmod(fileno(f
), 0644);
1852 m
->scheduled_shutdown_timeout
,
1853 m
->enable_wall_messages
,
1854 m
->scheduled_shutdown_type
);
1856 if (!isempty(m
->wall_message
)) {
1857 _cleanup_free_
char *t
;
1859 t
= cescape(m
->wall_message
);
1865 fprintf(f
, "WALL_MESSAGE=%s\n", t
);
1868 r
= fflush_and_check(f
);
1872 if (rename(temp_path
, "/run/systemd/shutdown/scheduled") < 0) {
1880 (void) unlink(temp_path
);
1881 (void) unlink("/run/systemd/shutdown/scheduled");
1883 return log_error_errno(r
, "Failed to write information about scheduled shutdowns: %m");
1886 static int manager_scheduled_shutdown_handler(
1891 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1892 Manager
*m
= userdata
;
1898 if (isempty(m
->scheduled_shutdown_type
))
1901 if (streq(m
->scheduled_shutdown_type
, "halt"))
1902 target
= SPECIAL_HALT_TARGET
;
1903 else if (streq(m
->scheduled_shutdown_type
, "poweroff"))
1904 target
= SPECIAL_POWEROFF_TARGET
;
1906 target
= SPECIAL_REBOOT_TARGET
;
1908 r
= execute_shutdown_or_sleep(m
, 0, target
, &error
);
1910 return log_error_errno(r
, "Unable to execute transition to %s: %m", target
);
1915 static int method_schedule_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1916 Manager
*m
= userdata
;
1917 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
1918 const char *action_multiple_sessions
= NULL
;
1919 const char *action_ignore_inhibit
= NULL
;
1920 const char *action
= NULL
;
1928 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
1932 if (startswith(type
, "dry-")) {
1934 m
->shutdown_dry_run
= true;
1937 if (streq(type
, "reboot")) {
1938 action
= "org.freedesktop.login1.reboot";
1939 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
1940 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
1941 } else if (streq(type
, "halt")) {
1942 action
= "org.freedesktop.login1.halt";
1943 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
1944 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
1945 } else if (streq(type
, "poweroff")) {
1946 action
= "org.freedesktop.login1.power-off";
1947 action_multiple_sessions
= "org.freedesktop.login1.power-off-multiple-sessions";
1948 action_ignore_inhibit
= "org.freedesktop.login1.power-off-ignore-inhibit";
1950 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
1952 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
1953 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
1957 if (m
->scheduled_shutdown_timeout_source
) {
1958 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
1960 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1962 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
1964 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1966 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
1967 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
1969 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1972 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
1974 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1978 if (m
->nologin_timeout_source
) {
1979 r
= sd_event_source_set_time(m
->nologin_timeout_source
, elapse
);
1981 return log_error_errno(r
, "sd_event_source_set_time() failed: %m");
1983 r
= sd_event_source_set_enabled(m
->nologin_timeout_source
, SD_EVENT_ONESHOT
);
1985 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m");
1987 r
= sd_event_add_time(m
->event
, &m
->nologin_timeout_source
,
1988 CLOCK_REALTIME
, elapse
- 5 * USEC_PER_MINUTE
, 0, nologin_timeout_handler
, m
);
1990 return log_error_errno(r
, "sd_event_add_time() failed: %m");
1993 m
->scheduled_shutdown_timeout
= elapse
;
1995 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
1997 const char *tty
= NULL
;
1999 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
2000 (void) sd_bus_creds_get_tty(creds
, &tty
);
2002 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
2004 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
2009 r
= manager_setup_wall_message_timer(m
);
2013 if (!isempty(type
)) {
2014 r
= update_schedule_file(m
);
2018 (void) unlink("/run/systemd/shutdown/scheduled");
2020 return sd_bus_reply_method_return(message
, NULL
);
2023 static int method_cancel_scheduled_shutdown(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2024 Manager
*m
= userdata
;
2030 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
2031 reset_scheduled_shutdown(m
);
2034 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2035 const char *tty
= NULL
;
2039 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
2041 (void) sd_bus_creds_get_uid(creds
, &uid
);
2042 (void) sd_bus_creds_get_tty(creds
, &tty
);
2045 utmp_wall("The system shutdown has been cancelled",
2046 uid_to_name(uid
), tty
, logind_wall_tty_filter
, m
);
2049 return sd_bus_reply_method_return(message
, "b", cancelled
);
2052 static int method_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2053 Manager
*m
= userdata
;
2055 return method_do_shutdown_or_sleep(
2057 SPECIAL_HIBERNATE_TARGET
,
2059 "org.freedesktop.login1.hibernate",
2060 "org.freedesktop.login1.hibernate-multiple-sessions",
2061 "org.freedesktop.login1.hibernate-ignore-inhibit",
2066 static int method_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2067 Manager
*m
= userdata
;
2069 return method_do_shutdown_or_sleep(
2071 SPECIAL_HYBRID_SLEEP_TARGET
,
2073 "org.freedesktop.login1.hibernate",
2074 "org.freedesktop.login1.hibernate-multiple-sessions",
2075 "org.freedesktop.login1.hibernate-ignore-inhibit",
2080 static int method_can_shutdown_or_sleep(
2082 sd_bus_message
*message
,
2085 const char *action_multiple_sessions
,
2086 const char *action_ignore_inhibit
,
2087 const char *sleep_verb
,
2088 sd_bus_error
*error
) {
2090 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2091 bool multiple_sessions
, challenge
, blocked
;
2092 const char *result
= NULL
;
2099 assert(w
<= _INHIBIT_WHAT_MAX
);
2101 assert(action_multiple_sessions
);
2102 assert(action_ignore_inhibit
);
2105 r
= can_sleep(sleep_verb
);
2109 return sd_bus_reply_method_return(message
, "s", "na");
2112 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
2116 r
= sd_bus_creds_get_euid(creds
, &uid
);
2120 r
= have_multiple_sessions(m
, uid
);
2124 multiple_sessions
= r
> 0;
2125 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
2127 if (multiple_sessions
) {
2128 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, NULL
, UID_INVALID
, &challenge
, error
);
2135 result
= "challenge";
2141 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, NULL
, UID_INVALID
, &challenge
, error
);
2145 if (r
> 0 && !result
)
2147 else if (challenge
&& (!result
|| streq(result
, "yes")))
2148 result
= "challenge";
2153 if (!multiple_sessions
&& !blocked
) {
2154 /* If neither inhibit nor multiple sessions
2155 * apply then just check the normal policy */
2157 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, NULL
, UID_INVALID
, &challenge
, error
);
2164 result
= "challenge";
2169 return sd_bus_reply_method_return(message
, "s", result
);
2172 static int method_can_poweroff(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2173 Manager
*m
= userdata
;
2175 return method_can_shutdown_or_sleep(
2178 "org.freedesktop.login1.power-off",
2179 "org.freedesktop.login1.power-off-multiple-sessions",
2180 "org.freedesktop.login1.power-off-ignore-inhibit",
2185 static int method_can_reboot(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2186 Manager
*m
= userdata
;
2188 return method_can_shutdown_or_sleep(
2191 "org.freedesktop.login1.reboot",
2192 "org.freedesktop.login1.reboot-multiple-sessions",
2193 "org.freedesktop.login1.reboot-ignore-inhibit",
2198 static int method_can_suspend(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2199 Manager
*m
= userdata
;
2201 return method_can_shutdown_or_sleep(
2204 "org.freedesktop.login1.suspend",
2205 "org.freedesktop.login1.suspend-multiple-sessions",
2206 "org.freedesktop.login1.suspend-ignore-inhibit",
2211 static int method_can_hibernate(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2212 Manager
*m
= userdata
;
2214 return method_can_shutdown_or_sleep(
2217 "org.freedesktop.login1.hibernate",
2218 "org.freedesktop.login1.hibernate-multiple-sessions",
2219 "org.freedesktop.login1.hibernate-ignore-inhibit",
2224 static int method_can_hybrid_sleep(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2225 Manager
*m
= userdata
;
2227 return method_can_shutdown_or_sleep(
2230 "org.freedesktop.login1.hibernate",
2231 "org.freedesktop.login1.hibernate-multiple-sessions",
2232 "org.freedesktop.login1.hibernate-ignore-inhibit",
2237 static int property_get_reboot_to_firmware_setup(
2240 const char *interface
,
2241 const char *property
,
2242 sd_bus_message
*reply
,
2244 sd_bus_error
*error
) {
2251 r
= efi_get_reboot_to_firmware();
2252 if (r
< 0 && r
!= -EOPNOTSUPP
)
2255 return sd_bus_message_append(reply
, "b", r
> 0);
2258 static int method_set_reboot_to_firmware_setup(
2259 sd_bus_message
*message
,
2261 sd_bus_error
*error
) {
2264 Manager
*m
= userdata
;
2269 r
= sd_bus_message_read(message
, "b", &b
);
2273 r
= bus_verify_polkit_async(message
,
2275 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2279 &m
->polkit_registry
,
2284 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2286 r
= efi_set_reboot_to_firmware(b
);
2290 return sd_bus_reply_method_return(message
, NULL
);
2293 static int method_can_reboot_to_firmware_setup(
2294 sd_bus_message
*message
,
2296 sd_bus_error
*error
) {
2301 Manager
*m
= userdata
;
2306 r
= efi_reboot_to_firmware_supported();
2307 if (r
== -EOPNOTSUPP
)
2308 return sd_bus_reply_method_return(message
, "s", "na");
2312 r
= bus_test_polkit(message
,
2314 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2325 result
= "challenge";
2329 return sd_bus_reply_method_return(message
, "s", result
);
2332 static int method_set_wall_message(
2333 sd_bus_message
*message
,
2335 sd_bus_error
*error
) {
2338 Manager
*m
= userdata
;
2340 int enable_wall_messages
;
2345 r
= sd_bus_message_read(message
, "sb", &wall_message
, &enable_wall_messages
);
2349 r
= bus_verify_polkit_async(message
,
2351 "org.freedesktop.login1.set-wall-message",
2355 &m
->polkit_registry
,
2360 return 1; /* Will call us back */
2362 if (isempty(wall_message
))
2363 m
->wall_message
= mfree(m
->wall_message
);
2365 r
= free_and_strdup(&m
->wall_message
, wall_message
);
2370 m
->enable_wall_messages
= enable_wall_messages
;
2372 return sd_bus_reply_method_return(message
, NULL
);
2375 static int method_inhibit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2376 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
2377 const char *who
, *why
, *what
, *mode
;
2378 _cleanup_free_
char *id
= NULL
;
2379 _cleanup_close_
int fifo_fd
= -1;
2380 Manager
*m
= userdata
;
2381 Inhibitor
*i
= NULL
;
2391 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2395 w
= inhibit_what_from_string(what
);
2397 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2399 mm
= inhibit_mode_from_string(mode
);
2401 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2403 /* Delay is only supported for shutdown/sleep */
2404 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2405 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2407 /* Don't allow taking delay locks while we are already
2408 * executing the operation. We shouldn't create the impression
2409 * that the lock was successful if the machine is about to go
2410 * down/suspend any moment. */
2411 if (m
->action_what
& w
)
2412 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2414 r
= bus_verify_polkit_async(
2417 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2418 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2419 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2420 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2421 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2422 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2423 "org.freedesktop.login1.inhibit-handle-lid-switch",
2427 &m
->polkit_registry
,
2432 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2434 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2438 r
= sd_bus_creds_get_euid(creds
, &uid
);
2442 r
= sd_bus_creds_get_pid(creds
, &pid
);
2449 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2452 } while (hashmap_get(m
->inhibitors
, id
));
2454 r
= manager_add_inhibitor(m
, id
, &i
);
2462 i
->why
= strdup(why
);
2463 i
->who
= strdup(who
);
2465 if (!i
->why
|| !i
->who
) {
2470 fifo_fd
= inhibitor_create_fifo(i
);
2478 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2487 const sd_bus_vtable manager_vtable
[] = {
2488 SD_BUS_VTABLE_START(0),
2490 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2491 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2493 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2494 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2495 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2496 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2497 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2498 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2499 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2500 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2501 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2502 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2503 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2504 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2505 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2506 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2507 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2508 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2509 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2510 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2511 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2512 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2513 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2514 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2515 SD_BUS_PROPERTY("Docked", "b", property_get_docked
, 0, 0),
2517 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2518 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2519 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2520 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2521 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2522 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2523 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2524 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2525 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2526 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2527 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2528 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2529 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2530 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2531 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2532 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2533 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2534 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2535 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2536 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2537 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2538 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2539 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2540 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2541 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2542 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2543 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2544 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2545 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2546 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2547 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2548 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2549 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2550 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2551 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2552 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2553 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2554 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2555 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2556 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2557 SD_BUS_METHOD("SetWallMessage", "sb", NULL
, method_set_wall_message
, SD_BUS_VTABLE_UNPRIVILEGED
),
2559 SD_BUS_SIGNAL("SessionNew", "so", 0),
2560 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2561 SD_BUS_SIGNAL("UserNew", "uo", 0),
2562 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2563 SD_BUS_SIGNAL("SeatNew", "so", 0),
2564 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2565 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2566 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2571 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2580 if (streq(result
, "done"))
2581 r
= session_send_create_reply(s
, NULL
);
2583 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
2585 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2586 r
= session_send_create_reply(s
, &e
);
2592 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2593 const char *path
, *result
, *unit
;
2594 Manager
*m
= userdata
;
2603 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2605 bus_log_parse_error(r
);
2609 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2610 log_info("Operation '%s' finished.", inhibit_what_to_string(m
->action_what
));
2612 /* Tell people that they now may take a lock again */
2613 send_prepare_for(m
, m
->action_what
, false);
2615 m
->action_job
= mfree(m
->action_job
);
2616 m
->action_unit
= NULL
;
2621 session
= hashmap_get(m
->session_units
, unit
);
2622 if (session
&& streq_ptr(path
, session
->scope_job
)) {
2623 session
->scope_job
= mfree(session
->scope_job
);
2624 session_jobs_reply(session
, unit
, result
);
2626 session_save(session
);
2627 user_save(session
->user
);
2628 session_add_to_gc_queue(session
);
2631 user
= hashmap_get(m
->user_units
, unit
);
2633 (streq_ptr(path
, user
->service_job
) ||
2634 streq_ptr(path
, user
->slice_job
))) {
2636 if (streq_ptr(path
, user
->service_job
))
2637 user
->service_job
= mfree(user
->service_job
);
2639 if (streq_ptr(path
, user
->slice_job
))
2640 user
->slice_job
= mfree(user
->slice_job
);
2642 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
)
2643 session_jobs_reply(session
, unit
, result
);
2646 user_add_to_gc_queue(user
);
2652 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2653 const char *path
, *unit
;
2654 Manager
*m
= userdata
;
2662 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2664 bus_log_parse_error(r
);
2668 session
= hashmap_get(m
->session_units
, unit
);
2670 session_add_to_gc_queue(session
);
2672 user
= hashmap_get(m
->user_units
, unit
);
2674 user_add_to_gc_queue(user
);
2679 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2680 _cleanup_free_
char *unit
= NULL
;
2681 Manager
*m
= userdata
;
2690 path
= sd_bus_message_get_path(message
);
2694 r
= unit_name_from_dbus_path(path
, &unit
);
2695 if (r
== -EINVAL
) /* not a unit */
2702 session
= hashmap_get(m
->session_units
, unit
);
2704 session_add_to_gc_queue(session
);
2706 user
= hashmap_get(m
->user_units
, unit
);
2708 user_add_to_gc_queue(user
);
2713 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2714 Manager
*m
= userdata
;
2722 r
= sd_bus_message_read(message
, "b", &b
);
2724 bus_log_parse_error(r
);
2731 /* systemd finished reloading, let's recheck all our sessions */
2732 log_debug("System manager has been reloaded, rechecking sessions...");
2734 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2735 session_add_to_gc_queue(session
);
2740 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2745 l
= strv_from_stdarg_alloca(property
);
2747 return sd_bus_emit_properties_changed_strv(
2749 "/org/freedesktop/login1",
2750 "org.freedesktop.login1.Manager",
2754 static int strdup_job(sd_bus_message
*reply
, char **job
) {
2759 r
= sd_bus_message_read(reply
, "o", &j
);
2771 int manager_start_slice(
2774 const char *description
,
2778 sd_bus_error
*error
,
2781 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
2788 r
= sd_bus_message_new_method_call(
2791 "org.freedesktop.systemd1",
2792 "/org/freedesktop/systemd1",
2793 "org.freedesktop.systemd1.Manager",
2794 "StartTransientUnit");
2798 r
= sd_bus_message_append(m
, "ss", strempty(slice
), "fail");
2802 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2806 if (!isempty(description
)) {
2807 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2812 if (!isempty(after
)) {
2813 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2818 if (!isempty(after2
)) {
2819 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2824 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
2828 r
= sd_bus_message_close_container(m
);
2832 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2836 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2840 return strdup_job(reply
, job
);
2843 int manager_start_scope(
2848 const char *description
,
2852 sd_bus_error
*error
,
2855 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
, *reply
= NULL
;
2863 r
= sd_bus_message_new_method_call(
2866 "org.freedesktop.systemd1",
2867 "/org/freedesktop/systemd1",
2868 "org.freedesktop.systemd1.Manager",
2869 "StartTransientUnit");
2873 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
2877 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2881 if (!isempty(slice
)) {
2882 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
2887 if (!isempty(description
)) {
2888 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2893 if (!isempty(after
)) {
2894 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2899 if (!isempty(after2
)) {
2900 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2905 /* cgroup empty notification is not available in containers
2906 * currently. To make this less problematic, let's shorten the
2907 * stop timeout for sessions, so that we don't wait
2910 /* Make sure that the session shells are terminated with
2911 * SIGHUP since bash and friends tend to ignore SIGTERM */
2912 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
2916 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
2920 r
= sd_bus_message_append(m
, "(sv)", "TasksMax", "t", tasks_max
);
2924 r
= sd_bus_message_close_container(m
);
2928 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2932 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2936 return strdup_job(reply
, job
);
2939 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2940 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2947 r
= sd_bus_call_method(
2949 "org.freedesktop.systemd1",
2950 "/org/freedesktop/systemd1",
2951 "org.freedesktop.systemd1.Manager",
2955 "ss", unit
, "replace");
2959 return strdup_job(reply
, job
);
2962 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2963 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2970 r
= sd_bus_call_method(
2972 "org.freedesktop.systemd1",
2973 "/org/freedesktop/systemd1",
2974 "org.freedesktop.systemd1.Manager",
2978 "ss", unit
, "fail");
2980 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2981 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
2984 sd_bus_error_free(error
);
2991 return strdup_job(reply
, job
);
2994 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
2995 _cleanup_free_
char *path
= NULL
;
3001 path
= unit_dbus_path_from_name(scope
);
3005 r
= sd_bus_call_method(
3007 "org.freedesktop.systemd1",
3009 "org.freedesktop.systemd1.Scope",
3015 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3016 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
3017 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
3018 sd_bus_error_free(error
);
3028 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
3032 return sd_bus_call_method(
3034 "org.freedesktop.systemd1",
3035 "/org/freedesktop/systemd1",
3036 "org.freedesktop.systemd1.Manager",
3040 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
3043 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
3044 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3045 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3046 _cleanup_free_
char *path
= NULL
;
3053 path
= unit_dbus_path_from_name(unit
);
3057 r
= sd_bus_get_property(
3059 "org.freedesktop.systemd1",
3061 "org.freedesktop.systemd1.Unit",
3067 /* systemd might have droppped off momentarily, let's
3068 * not make this an error */
3069 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3070 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3073 /* If the unit is already unloaded then it's not
3075 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
3076 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
3082 r
= sd_bus_message_read(reply
, "s", &state
);
3086 return !streq(state
, "inactive") && !streq(state
, "failed");
3089 int manager_job_is_active(Manager
*manager
, const char *path
) {
3090 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3091 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3097 r
= sd_bus_get_property(
3099 "org.freedesktop.systemd1",
3101 "org.freedesktop.systemd1.Job",
3107 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
3108 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
3111 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
3117 /* We don't actually care about the state really. The fact
3118 * that we could read the job state is enough for us */