1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "sd-messages.h"
30 #include "path-util.h"
32 #include "sleep-config.h"
33 #include "fileio-label.h"
34 #include "unit-name.h"
37 #include "bus-error.h"
38 #include "bus-common-errors.h"
39 #include "udev-util.h"
40 #include "selinux-util.h"
43 #include "formats-util.h"
44 #include "process-util.h"
45 #include "terminal-util.h"
46 #include "utmp-wtmp.h"
48 int manager_get_session_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Session
**ret
) {
49 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
58 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_SESSION
|SD_BUS_CREDS_AUGMENT
, &creds
);
62 r
= sd_bus_creds_get_session(creds
, &name
);
67 session
= hashmap_get(m
->sessions
, name
);
69 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SESSION
, "No session '%s' known", name
);
75 int manager_get_user_from_creds(Manager
*m
, sd_bus_message
*message
, uid_t uid
, sd_bus_error
*error
, User
**ret
) {
83 if (uid
== UID_INVALID
) {
84 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
86 /* Note that we get the owner UID of the session, not the actual client UID here! */
87 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
91 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
96 user
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
98 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER
, "No user "UID_FMT
" known or logged in", uid
);
104 int manager_get_seat_from_creds(Manager
*m
, sd_bus_message
*message
, const char *name
, sd_bus_error
*error
, Seat
**ret
) {
115 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
119 seat
= session
->seat
;
122 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "Session has no seat.");
124 seat
= hashmap_get(m
->seats
, name
);
126 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", name
);
133 static int property_get_idle_hint(
136 const char *interface
,
137 const char *property
,
138 sd_bus_message
*reply
,
140 sd_bus_error
*error
) {
142 Manager
*m
= userdata
;
148 return sd_bus_message_append(reply
, "b", manager_get_idle_hint(m
, NULL
) > 0);
151 static int property_get_idle_since_hint(
154 const char *interface
,
155 const char *property
,
156 sd_bus_message
*reply
,
158 sd_bus_error
*error
) {
160 Manager
*m
= userdata
;
167 manager_get_idle_hint(m
, &t
);
169 return sd_bus_message_append(reply
, "t", streq(property
, "IdleSinceHint") ? t
.realtime
: t
.monotonic
);
172 static int property_get_inhibited(
175 const char *interface
,
176 const char *property
,
177 sd_bus_message
*reply
,
179 sd_bus_error
*error
) {
181 Manager
*m
= userdata
;
188 w
= manager_inhibit_what(m
, streq(property
, "BlockInhibited") ? INHIBIT_BLOCK
: INHIBIT_DELAY
);
190 return sd_bus_message_append(reply
, "s", inhibit_what_to_string(w
));
193 static int property_get_preparing(
196 const char *interface
,
197 const char *property
,
198 sd_bus_message
*reply
,
200 sd_bus_error
*error
) {
202 Manager
*m
= userdata
;
209 if (streq(property
, "PreparingForShutdown"))
210 b
= !!(m
->action_what
& INHIBIT_SHUTDOWN
);
212 b
= !!(m
->action_what
& INHIBIT_SLEEP
);
214 return sd_bus_message_append(reply
, "b", b
);
217 static int property_get_scheduled_shutdown(
220 const char *interface
,
221 const char *property
,
222 sd_bus_message
*reply
,
224 sd_bus_error
*error
) {
226 Manager
*m
= userdata
;
233 r
= sd_bus_message_open_container(reply
, 'r', "st");
237 r
= sd_bus_message_append(reply
, "st", m
->scheduled_shutdown_type
, m
->scheduled_shutdown_timeout
);
241 return sd_bus_message_close_container(reply
);
244 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action
, handle_action
, HandleAction
);
246 static int method_get_session(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
247 _cleanup_free_
char *p
= NULL
;
248 Manager
*m
= userdata
;
257 r
= sd_bus_message_read(message
, "s", &name
);
261 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
265 p
= session_bus_path(session
);
269 return sd_bus_reply_method_return(message
, "o", p
);
272 static int method_get_session_by_pid(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
273 _cleanup_free_
char *p
= NULL
;
274 Session
*session
= NULL
;
275 Manager
*m
= userdata
;
283 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
285 r
= sd_bus_message_read(message
, "u", &pid
);
290 r
= manager_get_session_from_creds(m
, message
, NULL
, error
, &session
);
294 r
= manager_get_session_by_pid(m
, pid
, &session
);
299 return sd_bus_error_setf(error
, BUS_ERROR_NO_SESSION_FOR_PID
, "PID "PID_FMT
" does not belong to any known session", pid
);
302 p
= session_bus_path(session
);
306 return sd_bus_reply_method_return(message
, "o", p
);
309 static int method_get_user(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
310 _cleanup_free_
char *p
= NULL
;
311 Manager
*m
= userdata
;
320 r
= sd_bus_message_read(message
, "u", &uid
);
324 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
328 p
= user_bus_path(user
);
332 return sd_bus_reply_method_return(message
, "o", p
);
335 static int method_get_user_by_pid(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
336 _cleanup_free_
char *p
= NULL
;
337 Manager
*m
= userdata
;
346 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
348 r
= sd_bus_message_read(message
, "u", &pid
);
353 r
= manager_get_user_from_creds(m
, message
, UID_INVALID
, error
, &user
);
357 r
= manager_get_user_by_pid(m
, pid
, &user
);
361 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
);
364 p
= user_bus_path(user
);
368 return sd_bus_reply_method_return(message
, "o", p
);
371 static int method_get_seat(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
372 _cleanup_free_
char *p
= NULL
;
373 Manager
*m
= userdata
;
382 r
= sd_bus_message_read(message
, "s", &name
);
386 r
= manager_get_seat_from_creds(m
, message
, name
, error
, &seat
);
390 p
= seat_bus_path(seat
);
394 return sd_bus_reply_method_return(message
, "o", p
);
397 static int method_list_sessions(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
398 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
399 Manager
*m
= userdata
;
408 r
= sd_bus_message_new_method_return(message
, &reply
);
412 r
= sd_bus_message_open_container(reply
, 'a', "(susso)");
416 HASHMAP_FOREACH(session
, m
->sessions
, i
) {
417 _cleanup_free_
char *p
= NULL
;
419 p
= session_bus_path(session
);
423 r
= sd_bus_message_append(reply
, "(susso)",
425 (uint32_t) session
->user
->uid
,
427 session
->seat
? session
->seat
->id
: "",
433 r
= sd_bus_message_close_container(reply
);
437 return sd_bus_send(bus
, reply
, NULL
);
440 static int method_list_users(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
441 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
442 Manager
*m
= userdata
;
451 r
= sd_bus_message_new_method_return(message
, &reply
);
455 r
= sd_bus_message_open_container(reply
, 'a', "(uso)");
459 HASHMAP_FOREACH(user
, m
->users
, i
) {
460 _cleanup_free_
char *p
= NULL
;
462 p
= user_bus_path(user
);
466 r
= sd_bus_message_append(reply
, "(uso)",
467 (uint32_t) user
->uid
,
474 r
= sd_bus_message_close_container(reply
);
478 return sd_bus_send(bus
, reply
, NULL
);
481 static int method_list_seats(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
482 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
483 Manager
*m
= userdata
;
492 r
= sd_bus_message_new_method_return(message
, &reply
);
496 r
= sd_bus_message_open_container(reply
, 'a', "(so)");
500 HASHMAP_FOREACH(seat
, m
->seats
, i
) {
501 _cleanup_free_
char *p
= NULL
;
503 p
= seat_bus_path(seat
);
507 r
= sd_bus_message_append(reply
, "(so)", seat
->id
, p
);
512 r
= sd_bus_message_close_container(reply
);
516 return sd_bus_send(bus
, reply
, NULL
);
519 static int method_list_inhibitors(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
520 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
521 Manager
*m
= userdata
;
522 Inhibitor
*inhibitor
;
526 r
= sd_bus_message_new_method_return(message
, &reply
);
530 r
= sd_bus_message_open_container(reply
, 'a', "(ssssuu)");
534 HASHMAP_FOREACH(inhibitor
, m
->inhibitors
, i
) {
536 r
= sd_bus_message_append(reply
, "(ssssuu)",
537 strempty(inhibit_what_to_string(inhibitor
->what
)),
538 strempty(inhibitor
->who
),
539 strempty(inhibitor
->why
),
540 strempty(inhibit_mode_to_string(inhibitor
->mode
)),
541 (uint32_t) inhibitor
->uid
,
542 (uint32_t) inhibitor
->pid
);
547 r
= sd_bus_message_close_container(reply
);
551 return sd_bus_send(bus
, reply
, NULL
);
554 static int method_create_session(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
555 const char *service
, *type
, *class, *cseat
, *tty
, *display
, *remote_user
, *remote_host
, *desktop
;
556 uint32_t uid
, leader
, audit_id
= 0;
557 _cleanup_free_
char *id
= NULL
;
558 Session
*session
= NULL
;
559 Manager
*m
= userdata
;
572 r
= sd_bus_message_read(message
, "uusssssussbss", &uid
, &leader
, &service
, &type
, &class, &desktop
, &cseat
, &vtnr
, &tty
, &display
, &remote
, &remote_user
, &remote_host
);
577 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
580 t
= _SESSION_TYPE_INVALID
;
582 t
= session_type_from_string(type
);
584 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session type %s", type
);
588 c
= _SESSION_CLASS_INVALID
;
590 c
= session_class_from_string(class);
592 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid session class %s", class);
595 if (isempty(desktop
))
598 if (!string_is_safe(desktop
))
599 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid desktop string %s", desktop
);
605 seat
= hashmap_get(m
->seats
, cseat
);
607 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_SEAT
, "No seat '%s' known", cseat
);
610 if (tty_is_vc(tty
)) {
615 else if (seat
!= m
->seat0
)
616 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
);
618 v
= vtnr_from_tty(tty
);
620 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot determine VT number from virtual console TTY %s", tty
);
624 else if (vtnr
!= (uint32_t) v
)
625 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Specified TTY and VT number do not match");
627 } else if (tty_is_console(tty
)) {
631 else if (seat
!= m
->seat0
)
632 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but seat is not seat0");
635 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Console TTY specified but VT number is not 0");
639 if (seat_has_vts(seat
)) {
640 if (!vtnr
|| vtnr
> 63)
641 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "VT number out of range");
644 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Seat has no VTs but VT number not 0");
648 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
652 if (t
== _SESSION_TYPE_INVALID
) {
653 if (!isempty(display
))
655 else if (!isempty(tty
))
658 t
= SESSION_UNSPECIFIED
;
661 if (c
== _SESSION_CLASS_INVALID
) {
662 if (t
== SESSION_UNSPECIFIED
)
663 c
= SESSION_BACKGROUND
;
669 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
671 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
675 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
680 manager_get_session_by_pid(m
, leader
, &session
);
682 _cleanup_free_
char *path
= NULL
;
683 _cleanup_close_
int fifo_fd
= -1;
685 /* Session already exists, client is probably
686 * something like "su" which changes uid but is still
687 * the same session */
689 fifo_fd
= session_create_fifo(session
);
693 path
= session_bus_path(session
);
697 log_debug("Sending reply about an existing session: "
698 "id=%s object_path=%s uid=%u runtime_path=%s "
699 "session_fd=%d seat=%s vtnr=%u",
702 (uint32_t) session
->user
->uid
,
703 session
->user
->runtime_path
,
705 session
->seat
? session
->seat
->id
: "",
706 (uint32_t) session
->vtnr
);
708 return sd_bus_reply_method_return(
712 session
->user
->runtime_path
,
714 (uint32_t) session
->user
->uid
,
715 session
->seat
? session
->seat
->id
: "",
716 (uint32_t) session
->vtnr
,
720 audit_session_from_pid(leader
, &audit_id
);
722 /* Keep our session IDs and the audit session IDs in sync */
724 if (asprintf(&id
, "%"PRIu32
, audit_id
) < 0)
727 /* Wut? There's already a session by this name and we
728 * didn't find it above? Weird, then let's not trust
729 * the audit data and let's better register a new
731 if (hashmap_get(m
->sessions
, id
)) {
732 log_warning("Existing logind session ID %s used by new audit session, ignoring", id
);
745 if (asprintf(&id
, "c%lu", ++m
->session_counter
) < 0)
748 } while (hashmap_get(m
->sessions
, id
));
751 r
= manager_add_user_by_uid(m
, uid
, &user
);
755 r
= manager_add_session(m
, id
, &session
);
759 session_set_user(session
, user
);
761 session
->leader
= leader
;
762 session
->audit_id
= audit_id
;
765 session
->remote
= remote
;
766 session
->vtnr
= vtnr
;
769 session
->tty
= strdup(tty
);
776 if (!isempty(display
)) {
777 session
->display
= strdup(display
);
778 if (!session
->display
) {
784 if (!isempty(remote_user
)) {
785 session
->remote_user
= strdup(remote_user
);
786 if (!session
->remote_user
) {
792 if (!isempty(remote_host
)) {
793 session
->remote_host
= strdup(remote_host
);
794 if (!session
->remote_host
) {
800 if (!isempty(service
)) {
801 session
->service
= strdup(service
);
802 if (!session
->service
) {
808 if (!isempty(desktop
)) {
809 session
->desktop
= strdup(desktop
);
810 if (!session
->desktop
) {
817 r
= seat_attach_session(seat
, session
);
822 r
= session_start(session
);
826 session
->create_message
= sd_bus_message_ref(message
);
828 /* Now, let's wait until the slice unit and stuff got
829 * created. We send the reply back from
830 * session_send_create_reply(). */
836 session_add_to_gc_queue(session
);
839 user_add_to_gc_queue(user
);
844 static int method_release_session(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
845 Manager
*m
= userdata
;
854 r
= sd_bus_message_read(message
, "s", &name
);
858 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
862 r
= session_release(session
);
866 return sd_bus_reply_method_return(message
, NULL
);
869 static int method_activate_session(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
870 Manager
*m
= userdata
;
879 r
= sd_bus_message_read(message
, "s", &name
);
883 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
887 return bus_session_method_activate(bus
, message
, session
, error
);
890 static int method_activate_session_on_seat(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
891 const char *session_name
, *seat_name
;
892 Manager
*m
= userdata
;
901 /* Same as ActivateSession() but refuses to work if
902 * the seat doesn't match */
904 r
= sd_bus_message_read(message
, "ss", &session_name
, &seat_name
);
908 r
= manager_get_session_from_creds(m
, message
, session_name
, error
, &session
);
912 r
= manager_get_seat_from_creds(m
, message
, seat_name
, error
, &seat
);
916 if (session
->seat
!= seat
)
917 return sd_bus_error_setf(error
, BUS_ERROR_SESSION_NOT_ON_SEAT
, "Session %s not on seat %s", session_name
, seat_name
);
919 r
= session_activate(session
);
923 return sd_bus_reply_method_return(message
, NULL
);
926 static int method_lock_session(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
927 Manager
*m
= userdata
;
936 r
= sd_bus_message_read(message
, "s", &name
);
940 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
944 return bus_session_method_lock(bus
, message
, session
, error
);
947 static int method_lock_sessions(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
948 Manager
*m
= userdata
;
955 r
= bus_verify_polkit_async(
958 "org.freedesktop.login1.lock-sessions",
966 return 1; /* Will call us back */
968 r
= session_send_lock_all(m
, streq(sd_bus_message_get_member(message
), "LockSessions"));
972 return sd_bus_reply_method_return(message
, NULL
);
975 static int method_kill_session(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
977 Manager
*m
= userdata
;
985 r
= sd_bus_message_read(message
, "s", &name
);
989 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
993 return bus_session_method_kill(bus
, message
, session
, error
);
996 static int method_kill_user(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
997 Manager
*m
= userdata
;
1006 r
= sd_bus_message_read(message
, "u", &uid
);
1010 r
= manager_get_user_from_creds(m
, message
, uid
, error
, &user
);
1014 return bus_user_method_kill(bus
, message
, user
, error
);
1017 static int method_terminate_session(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1018 Manager
*m
= userdata
;
1027 r
= sd_bus_message_read(message
, "s", &name
);
1031 r
= manager_get_session_from_creds(m
, message
, name
, error
, &session
);
1035 return bus_session_method_terminate(bus
, message
, session
, error
);
1038 static int method_terminate_user(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1039 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(bus
, message
, user
, error
);
1059 static int method_terminate_seat(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1060 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(bus
, message
, seat
, error
);
1080 static int method_set_user_linger(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1081 _cleanup_free_
char *cc
= NULL
;
1082 Manager
*m
= userdata
;
1093 r
= sd_bus_message_read(message
, "ubb", &uid
, &b
, &interactive
);
1097 if (uid
== UID_INVALID
) {
1098 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1100 /* Note that we get the owner UID of the session, not the actual client UID here! */
1101 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_OWNER_UID
|SD_BUS_CREDS_AUGMENT
, &creds
);
1105 r
= sd_bus_creds_get_owner_uid(creds
, &uid
);
1113 return errno
? -errno
: -ENOENT
;
1115 r
= bus_verify_polkit_async(
1118 "org.freedesktop.login1.set-user-linger",
1121 &m
->polkit_registry
,
1126 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1128 mkdir_p_label("/var/lib/systemd", 0755);
1130 r
= mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1134 cc
= cescape(pw
->pw_name
);
1138 path
= strjoina("/var/lib/systemd/linger/", cc
);
1146 if (manager_add_user_by_uid(m
, uid
, &u
) >= 0)
1153 if (r
< 0 && errno
!= ENOENT
)
1156 u
= hashmap_get(m
->users
, UID_TO_PTR(uid
));
1158 user_add_to_gc_queue(u
);
1161 return sd_bus_reply_method_return(message
, NULL
);
1164 static int trigger_device(Manager
*m
, struct udev_device
*d
) {
1165 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
1166 struct udev_list_entry
*first
, *item
;
1171 e
= udev_enumerate_new(m
->udev
);
1176 r
= udev_enumerate_add_match_parent(e
, d
);
1181 r
= udev_enumerate_scan_devices(e
);
1185 first
= udev_enumerate_get_list_entry(e
);
1186 udev_list_entry_foreach(item
, first
) {
1187 _cleanup_free_
char *t
= NULL
;
1190 p
= udev_list_entry_get_name(item
);
1192 t
= strappend(p
, "/uevent");
1196 write_string_file(t
, "change");
1202 static int attach_device(Manager
*m
, const char *seat
, const char *sysfs
) {
1203 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
1204 _cleanup_free_
char *rule
= NULL
, *file
= NULL
;
1205 const char *id_for_seat
;
1212 d
= udev_device_new_from_syspath(m
->udev
, sysfs
);
1216 if (!udev_device_has_tag(d
, "seat"))
1219 id_for_seat
= udev_device_get_property_value(d
, "ID_FOR_SEAT");
1223 if (asprintf(&file
, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat
) < 0)
1226 if (asprintf(&rule
, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat
, seat
) < 0)
1229 mkdir_p_label("/etc/udev/rules.d", 0755);
1230 mac_selinux_init("/etc");
1231 r
= write_string_file_atomic_label(file
, rule
);
1235 return trigger_device(m
, d
);
1238 static int flush_devices(Manager
*m
) {
1239 _cleanup_closedir_
DIR *d
;
1243 d
= opendir("/etc/udev/rules.d");
1245 if (errno
!= ENOENT
)
1246 log_warning_errno(errno
, "Failed to open /etc/udev/rules.d: %m");
1250 while ((de
= readdir(d
))) {
1252 if (!dirent_is_file(de
))
1255 if (!startswith(de
->d_name
, "72-seat-"))
1258 if (!endswith(de
->d_name
, ".rules"))
1261 if (unlinkat(dirfd(d
), de
->d_name
, 0) < 0)
1262 log_warning_errno(errno
, "Failed to unlink %s: %m", de
->d_name
);
1266 return trigger_device(m
, NULL
);
1269 static int method_attach_device(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1270 const char *sysfs
, *seat
;
1271 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",
1294 &m
->polkit_registry
,
1299 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1301 r
= attach_device(m
, seat
, sysfs
);
1305 return sd_bus_reply_method_return(message
, NULL
);
1308 static int method_flush_devices(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1309 Manager
*m
= userdata
;
1316 r
= sd_bus_message_read(message
, "b", &interactive
);
1320 r
= bus_verify_polkit_async(
1323 "org.freedesktop.login1.flush-devices",
1326 &m
->polkit_registry
,
1331 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1333 r
= flush_devices(m
);
1337 return sd_bus_reply_method_return(message
, NULL
);
1340 static int have_multiple_sessions(
1349 /* Check for other users' sessions. Greeter sessions do not
1350 * count, and non-login sessions do not count either. */
1351 HASHMAP_FOREACH(session
, m
->sessions
, i
)
1352 if (session
->class == SESSION_USER
&&
1353 session
->user
->uid
!= uid
)
1359 static int bus_manager_log_shutdown(
1362 const char *unit_name
) {
1369 if (w
!= INHIBIT_SHUTDOWN
)
1372 if (streq(unit_name
, SPECIAL_POWEROFF_TARGET
)) {
1373 p
= "MESSAGE=System is powering down.";
1374 q
= "SHUTDOWN=power-off";
1375 } else if (streq(unit_name
, SPECIAL_HALT_TARGET
)) {
1376 p
= "MESSAGE=System is halting.";
1377 q
= "SHUTDOWN=halt";
1378 } else if (streq(unit_name
, SPECIAL_REBOOT_TARGET
)) {
1379 p
= "MESSAGE=System is rebooting.";
1380 q
= "SHUTDOWN=reboot";
1381 } else if (streq(unit_name
, SPECIAL_KEXEC_TARGET
)) {
1382 p
= "MESSAGE=System is rebooting with kexec.";
1383 q
= "SHUTDOWN=kexec";
1385 p
= "MESSAGE=System is shutting down.";
1389 return log_struct(LOG_NOTICE
,
1390 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN
),
1396 static int lid_switch_ignore_handler(sd_event_source
*e
, uint64_t usec
, void *userdata
) {
1397 Manager
*m
= userdata
;
1402 m
->lid_switch_ignore_event_source
= sd_event_source_unref(m
->lid_switch_ignore_event_source
);
1406 int manager_set_lid_switch_ignore(Manager
*m
, usec_t until
) {
1411 if (until
<= now(CLOCK_MONOTONIC
))
1414 /* We want to ignore the lid switch for a while after each
1415 * suspend, and after boot-up. Hence let's install a timer for
1416 * this. As long as the event source exists we ignore the lid
1419 if (m
->lid_switch_ignore_event_source
) {
1422 r
= sd_event_source_get_time(m
->lid_switch_ignore_event_source
, &u
);
1429 r
= sd_event_source_set_time(m
->lid_switch_ignore_event_source
, until
);
1431 r
= sd_event_add_time(
1433 &m
->lid_switch_ignore_event_source
,
1436 lid_switch_ignore_handler
, m
);
1441 static int execute_shutdown_or_sleep(
1444 const char *unit_name
,
1445 sd_bus_error
*error
) {
1447 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1454 assert(w
< _INHIBIT_WHAT_MAX
);
1457 bus_manager_log_shutdown(m
, w
, unit_name
);
1459 r
= sd_bus_call_method(
1461 "org.freedesktop.systemd1",
1462 "/org/freedesktop/systemd1",
1463 "org.freedesktop.systemd1.Manager",
1467 "ss", unit_name
, "replace-irreversibly");
1471 r
= sd_bus_message_read(reply
, "o", &p
);
1479 m
->action_unit
= unit_name
;
1480 free(m
->action_job
);
1484 /* Make sure the lid switch is ignored for a while */
1485 manager_set_lid_switch_ignore(m
, now(CLOCK_MONOTONIC
) + m
->holdoff_timeout_usec
);
1490 static int manager_inhibit_timeout_handler(
1495 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1496 Inhibitor
*offending
= NULL
;
1497 Manager
*manager
= userdata
;
1501 assert(manager
->inhibit_timeout_source
== s
);
1503 if (manager
->action_what
== 0 || manager
->action_job
)
1506 if (manager_is_inhibited(manager
, manager
->action_what
, INHIBIT_DELAY
, NULL
, false, false, 0, &offending
)) {
1507 _cleanup_free_
char *comm
= NULL
, *u
= NULL
;
1509 (void) get_process_comm(offending
->pid
, &comm
);
1510 u
= uid_to_name(offending
->uid
);
1512 log_notice("Delay lock is active (UID "UID_FMT
"/%s, PID "PID_FMT
"/%s) but inhibitor timeout is reached.",
1513 offending
->uid
, strna(u
),
1514 offending
->pid
, strna(comm
));
1517 /* Actually do the operation */
1518 r
= execute_shutdown_or_sleep(manager
, manager
->action_what
, manager
->action_unit
, &error
);
1520 log_warning("Failed to send delayed message: %s", bus_error_message(&error
, r
));
1522 manager
->action_unit
= NULL
;
1523 manager
->action_what
= 0;
1529 static int delay_shutdown_or_sleep(
1532 const char *unit_name
) {
1539 assert(w
< _INHIBIT_WHAT_MAX
);
1542 timeout_val
= now(CLOCK_MONOTONIC
) + m
->inhibit_delay_max
;
1544 if (m
->inhibit_timeout_source
) {
1545 r
= sd_event_source_set_time(m
->inhibit_timeout_source
, timeout_val
);
1547 return log_error_errno(r
, "sd_event_source_set_time() failed: %m\n");
1549 r
= sd_event_source_set_enabled(m
->inhibit_timeout_source
, SD_EVENT_ONESHOT
);
1551 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m\n");
1553 r
= sd_event_add_time(m
->event
, &m
->inhibit_timeout_source
, CLOCK_MONOTONIC
,
1554 timeout_val
, 0, manager_inhibit_timeout_handler
, m
);
1559 m
->action_unit
= unit_name
;
1565 static int send_prepare_for(Manager
*m
, InhibitWhat w
, bool _active
) {
1567 static const char * const signal_name
[_INHIBIT_WHAT_MAX
] = {
1568 [INHIBIT_SHUTDOWN
] = "PrepareForShutdown",
1569 [INHIBIT_SLEEP
] = "PrepareForSleep"
1572 int active
= _active
;
1576 assert(w
< _INHIBIT_WHAT_MAX
);
1577 assert(signal_name
[w
]);
1579 return sd_bus_emit_signal(m
->bus
,
1580 "/org/freedesktop/login1",
1581 "org.freedesktop.login1.Manager",
1587 int bus_manager_shutdown_or_sleep_now_or_later(
1589 const char *unit_name
,
1591 sd_bus_error
*error
) {
1599 assert(w
<= _INHIBIT_WHAT_MAX
);
1600 assert(!m
->action_job
);
1602 /* Tell everybody to prepare for shutdown/sleep */
1603 send_prepare_for(m
, w
, true);
1606 m
->inhibit_delay_max
> 0 &&
1607 manager_is_inhibited(m
, w
, INHIBIT_DELAY
, NULL
, false, false, 0, NULL
);
1610 /* Shutdown is delayed, keep in mind what we
1611 * want to do, and start a timeout */
1612 r
= delay_shutdown_or_sleep(m
, w
, unit_name
);
1614 /* Shutdown is not delayed, execute it
1616 r
= execute_shutdown_or_sleep(m
, w
, unit_name
, error
);
1621 static int verify_shutdown_creds(
1623 sd_bus_message
*message
,
1627 const char *action_multiple_sessions
,
1628 const char *action_ignore_inhibit
,
1629 sd_bus_error
*error
) {
1631 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1632 bool multiple_sessions
, blocked
;
1639 assert(w
<= _INHIBIT_WHAT_MAX
);
1641 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1645 r
= sd_bus_creds_get_euid(creds
, &uid
);
1649 r
= have_multiple_sessions(m
, uid
);
1653 multiple_sessions
= r
> 0;
1654 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1656 if (multiple_sessions
&& action_multiple_sessions
) {
1657 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_multiple_sessions
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1661 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1664 if (blocked
&& action_ignore_inhibit
) {
1665 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1669 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1672 if (!multiple_sessions
&& !blocked
&& action
) {
1673 r
= bus_verify_polkit_async(message
, CAP_SYS_BOOT
, action
, interactive
, UID_INVALID
, &m
->polkit_registry
, error
);
1677 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1683 static int method_do_shutdown_or_sleep(
1685 sd_bus_message
*message
,
1686 const char *unit_name
,
1689 const char *action_multiple_sessions
,
1690 const char *action_ignore_inhibit
,
1691 const char *sleep_verb
,
1692 sd_bus_error
*error
) {
1700 assert(w
<= _INHIBIT_WHAT_MAX
);
1702 r
= sd_bus_message_read(message
, "b", &interactive
);
1706 /* Don't allow multiple jobs being executed at the same time */
1708 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "There's already a shutdown or sleep operation in progress");
1711 r
= can_sleep(sleep_verb
);
1716 return sd_bus_error_setf(error
, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED
, "Sleep verb not supported");
1719 r
= verify_shutdown_creds(m
, message
, w
, interactive
, action
, action_multiple_sessions
,
1720 action_ignore_inhibit
, error
);
1724 r
= bus_manager_shutdown_or_sleep_now_or_later(m
, unit_name
, w
, error
);
1728 return sd_bus_reply_method_return(message
, NULL
);
1731 static int method_poweroff(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1732 Manager
*m
= userdata
;
1734 return method_do_shutdown_or_sleep(
1736 SPECIAL_POWEROFF_TARGET
,
1738 "org.freedesktop.login1.power-off",
1739 "org.freedesktop.login1.power-off-multiple-sessions",
1740 "org.freedesktop.login1.power-off-ignore-inhibit",
1745 static int method_reboot(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1746 Manager
*m
= userdata
;
1748 return method_do_shutdown_or_sleep(
1750 SPECIAL_REBOOT_TARGET
,
1752 "org.freedesktop.login1.reboot",
1753 "org.freedesktop.login1.reboot-multiple-sessions",
1754 "org.freedesktop.login1.reboot-ignore-inhibit",
1759 static int method_suspend(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1760 Manager
*m
= userdata
;
1762 return method_do_shutdown_or_sleep(
1764 SPECIAL_SUSPEND_TARGET
,
1766 "org.freedesktop.login1.suspend",
1767 "org.freedesktop.login1.suspend-multiple-sessions",
1768 "org.freedesktop.login1.suspend-ignore-inhibit",
1773 static int manager_scheduled_shutdown_handler(
1778 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1779 Manager
*m
= userdata
;
1785 if (isempty(m
->scheduled_shutdown_type
))
1788 if (streq(m
->scheduled_shutdown_type
, "halt"))
1789 target
= SPECIAL_HALT_TARGET
;
1790 else if (streq(m
->scheduled_shutdown_type
, "poweroff"))
1791 target
= SPECIAL_POWEROFF_TARGET
;
1793 target
= SPECIAL_REBOOT_TARGET
;
1795 r
= execute_shutdown_or_sleep(m
, 0, target
, &error
);
1797 return log_error_errno(r
, "Unable to execute transition to %s: %m\n", target
);
1802 static int method_schedule_shutdown(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1803 Manager
*m
= userdata
;
1804 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1805 const char *action_multiple_sessions
= NULL
;
1806 const char *action_ignore_inhibit
= NULL
;
1807 const char *action
= NULL
;
1815 r
= sd_bus_message_read(message
, "st", &type
, &elapse
);
1819 if (streq(type
, "reboot")) {
1820 action
= "org.freedesktop.login1.reboot";
1821 action_multiple_sessions
= "org.freedesktop.login1.reboot-multiple-sessions";
1822 action_ignore_inhibit
= "org.freedesktop.login1.reboot-ignore-inhibit";
1823 } else if (streq(type
, "halt")) {
1824 action
= "org.freedesktop.login1.halt";
1825 action_multiple_sessions
= "org.freedesktop.login1.halt-multiple-sessions";
1826 action_ignore_inhibit
= "org.freedesktop.login1.halt-ignore-inhibit";
1827 } else if (streq(type
, "poweroff")) {
1828 action
= "org.freedesktop.login1.poweroff";
1829 action_multiple_sessions
= "org.freedesktop.login1.poweroff-multiple-sessions";
1830 action_ignore_inhibit
= "org.freedesktop.login1.poweroff-ignore-inhibit";
1832 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unsupported shutdown type");
1834 r
= verify_shutdown_creds(m
, message
, INHIBIT_SHUTDOWN
, false,
1835 action
, action_multiple_sessions
, action_ignore_inhibit
, error
);
1839 if (m
->scheduled_shutdown_timeout_source
) {
1840 r
= sd_event_source_set_time(m
->scheduled_shutdown_timeout_source
, elapse
);
1842 return log_error_errno(r
, "sd_event_source_set_time() failed: %m\n");
1844 r
= sd_event_source_set_enabled(m
->scheduled_shutdown_timeout_source
, SD_EVENT_ONESHOT
);
1846 return log_error_errno(r
, "sd_event_source_set_enabled() failed: %m\n");
1848 r
= sd_event_add_time(m
->event
, &m
->scheduled_shutdown_timeout_source
,
1849 CLOCK_REALTIME
, elapse
, 0, manager_scheduled_shutdown_handler
, m
);
1851 return log_error_errno(r
, "sd_event_add_time() failed: %m\n");
1854 r
= free_and_strdup(&m
->scheduled_shutdown_type
, type
);
1856 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1860 m
->scheduled_shutdown_timeout
= elapse
;
1862 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
1866 (void) sd_bus_creds_get_uid(creds
, &m
->scheduled_shutdown_uid
);
1867 (void) sd_bus_creds_get_tty(creds
, &tty
);
1869 r
= free_and_strdup(&m
->scheduled_shutdown_tty
, tty
);
1871 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1876 r
= manager_setup_wall_message_timer(m
);
1880 return sd_bus_reply_method_return(message
, NULL
);
1883 static int method_cancel_scheduled_shutdown(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1884 Manager
*m
= userdata
;
1890 cancelled
= m
->scheduled_shutdown_type
!= NULL
;
1892 m
->scheduled_shutdown_timeout_source
= sd_event_source_unref(m
->scheduled_shutdown_timeout_source
);
1893 m
->wall_message_timeout_source
= sd_event_source_unref(m
->wall_message_timeout_source
);
1894 free(m
->scheduled_shutdown_type
);
1895 m
->scheduled_shutdown_type
= NULL
;
1896 m
->scheduled_shutdown_timeout
= 0;
1899 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1900 const char *tty
= NULL
;
1904 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_AUGMENT
|SD_BUS_CREDS_TTY
|SD_BUS_CREDS_UID
, &creds
);
1906 (void) sd_bus_creds_get_uid(creds
, &uid
);
1907 (void) sd_bus_creds_get_tty(creds
, &tty
);
1910 utmp_wall("The system shutdown has been cancelled",
1911 lookup_uid(uid
), tty
, logind_wall_tty_filter
, m
);
1914 return sd_bus_reply_method_return(message
, "b", cancelled
);
1917 static int method_hibernate(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1918 Manager
*m
= userdata
;
1920 return method_do_shutdown_or_sleep(
1922 SPECIAL_HIBERNATE_TARGET
,
1924 "org.freedesktop.login1.hibernate",
1925 "org.freedesktop.login1.hibernate-multiple-sessions",
1926 "org.freedesktop.login1.hibernate-ignore-inhibit",
1931 static int method_hybrid_sleep(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1932 Manager
*m
= userdata
;
1934 return method_do_shutdown_or_sleep(
1936 SPECIAL_HYBRID_SLEEP_TARGET
,
1938 "org.freedesktop.login1.hibernate",
1939 "org.freedesktop.login1.hibernate-multiple-sessions",
1940 "org.freedesktop.login1.hibernate-ignore-inhibit",
1945 static int method_can_shutdown_or_sleep(
1947 sd_bus_message
*message
,
1950 const char *action_multiple_sessions
,
1951 const char *action_ignore_inhibit
,
1952 const char *sleep_verb
,
1953 sd_bus_error
*error
) {
1955 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
1956 bool multiple_sessions
, challenge
, blocked
;
1957 const char *result
= NULL
;
1964 assert(w
<= _INHIBIT_WHAT_MAX
);
1966 assert(action_multiple_sessions
);
1967 assert(action_ignore_inhibit
);
1970 r
= can_sleep(sleep_verb
);
1974 return sd_bus_reply_method_return(message
, "s", "na");
1977 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
, &creds
);
1981 r
= sd_bus_creds_get_euid(creds
, &uid
);
1985 r
= have_multiple_sessions(m
, uid
);
1989 multiple_sessions
= r
> 0;
1990 blocked
= manager_is_inhibited(m
, w
, INHIBIT_BLOCK
, NULL
, false, true, uid
, NULL
);
1992 if (multiple_sessions
) {
1993 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_multiple_sessions
, UID_INVALID
, &challenge
, error
);
2000 result
= "challenge";
2006 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action_ignore_inhibit
, UID_INVALID
, &challenge
, error
);
2010 if (r
> 0 && !result
)
2012 else if (challenge
&& (!result
|| streq(result
, "yes")))
2013 result
= "challenge";
2018 if (!multiple_sessions
&& !blocked
) {
2019 /* If neither inhibit nor multiple sessions
2020 * apply then just check the normal policy */
2022 r
= bus_test_polkit(message
, CAP_SYS_BOOT
, action
, UID_INVALID
, &challenge
, error
);
2029 result
= "challenge";
2034 return sd_bus_reply_method_return(message
, "s", result
);
2037 static int method_can_poweroff(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2038 Manager
*m
= userdata
;
2040 return method_can_shutdown_or_sleep(
2043 "org.freedesktop.login1.power-off",
2044 "org.freedesktop.login1.power-off-multiple-sessions",
2045 "org.freedesktop.login1.power-off-ignore-inhibit",
2050 static int method_can_reboot(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2051 Manager
*m
= userdata
;
2053 return method_can_shutdown_or_sleep(
2056 "org.freedesktop.login1.reboot",
2057 "org.freedesktop.login1.reboot-multiple-sessions",
2058 "org.freedesktop.login1.reboot-ignore-inhibit",
2063 static int method_can_suspend(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2064 Manager
*m
= userdata
;
2066 return method_can_shutdown_or_sleep(
2069 "org.freedesktop.login1.suspend",
2070 "org.freedesktop.login1.suspend-multiple-sessions",
2071 "org.freedesktop.login1.suspend-ignore-inhibit",
2076 static int method_can_hibernate(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2077 Manager
*m
= userdata
;
2079 return method_can_shutdown_or_sleep(
2082 "org.freedesktop.login1.hibernate",
2083 "org.freedesktop.login1.hibernate-multiple-sessions",
2084 "org.freedesktop.login1.hibernate-ignore-inhibit",
2089 static int method_can_hybrid_sleep(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2090 Manager
*m
= userdata
;
2092 return method_can_shutdown_or_sleep(
2095 "org.freedesktop.login1.hibernate",
2096 "org.freedesktop.login1.hibernate-multiple-sessions",
2097 "org.freedesktop.login1.hibernate-ignore-inhibit",
2102 static int property_get_reboot_to_firmware_setup(
2105 const char *interface
,
2106 const char *property
,
2107 sd_bus_message
*reply
,
2109 sd_bus_error
*error
) {
2116 r
= efi_get_reboot_to_firmware();
2117 if (r
< 0 && r
!= -EOPNOTSUPP
)
2120 return sd_bus_message_append(reply
, "b", r
> 0);
2123 static int method_set_reboot_to_firmware_setup(
2125 sd_bus_message
*message
,
2127 sd_bus_error
*error
) {
2130 Manager
*m
= userdata
;
2136 r
= sd_bus_message_read(message
, "b", &b
);
2140 r
= bus_verify_polkit_async(message
,
2142 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2145 &m
->polkit_registry
,
2150 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2152 r
= efi_set_reboot_to_firmware(b
);
2156 return sd_bus_reply_method_return(message
, NULL
);
2159 static int method_can_reboot_to_firmware_setup(
2161 sd_bus_message
*message
,
2163 sd_bus_error
*error
) {
2168 Manager
*m
= userdata
;
2174 r
= efi_reboot_to_firmware_supported();
2175 if (r
== -EOPNOTSUPP
)
2176 return sd_bus_reply_method_return(message
, "s", "na");
2180 r
= bus_test_polkit(message
,
2182 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2192 result
= "challenge";
2196 return sd_bus_reply_method_return(message
, "s", result
);
2199 static int method_inhibit(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2200 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
2201 const char *who
, *why
, *what
, *mode
;
2202 _cleanup_free_
char *id
= NULL
;
2203 _cleanup_close_
int fifo_fd
= -1;
2204 Manager
*m
= userdata
;
2205 Inhibitor
*i
= NULL
;
2216 r
= sd_bus_message_read(message
, "ssss", &what
, &who
, &why
, &mode
);
2220 w
= inhibit_what_from_string(what
);
2222 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid what specification %s", what
);
2224 mm
= inhibit_mode_from_string(mode
);
2226 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid mode specification %s", mode
);
2228 /* Delay is only supported for shutdown/sleep */
2229 if (mm
== INHIBIT_DELAY
&& (w
& ~(INHIBIT_SHUTDOWN
|INHIBIT_SLEEP
)))
2230 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delay inhibitors only supported for shutdown and sleep");
2232 /* Don't allow taking delay locks while we are already
2233 * executing the operation. We shouldn't create the impression
2234 * that the lock was successful if the machine is about to go
2235 * down/suspend any moment. */
2236 if (m
->action_what
& w
)
2237 return sd_bus_error_setf(error
, BUS_ERROR_OPERATION_IN_PROGRESS
, "The operation inhibition has been requested for is already running");
2239 r
= bus_verify_polkit_async(
2242 w
== INHIBIT_SHUTDOWN
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2243 w
== INHIBIT_SLEEP
? (mm
== INHIBIT_BLOCK
? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2244 w
== INHIBIT_IDLE
? "org.freedesktop.login1.inhibit-block-idle" :
2245 w
== INHIBIT_HANDLE_POWER_KEY
? "org.freedesktop.login1.inhibit-handle-power-key" :
2246 w
== INHIBIT_HANDLE_SUSPEND_KEY
? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2247 w
== INHIBIT_HANDLE_HIBERNATE_KEY
? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2248 "org.freedesktop.login1.inhibit-handle-lid-switch",
2251 &m
->polkit_registry
,
2256 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2258 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_EUID
|SD_BUS_CREDS_PID
, &creds
);
2262 r
= sd_bus_creds_get_euid(creds
, &uid
);
2266 r
= sd_bus_creds_get_pid(creds
, &pid
);
2274 if (asprintf(&id
, "%lu", ++m
->inhibit_counter
) < 0)
2277 } while (hashmap_get(m
->inhibitors
, id
));
2279 r
= manager_add_inhibitor(m
, id
, &i
);
2287 i
->why
= strdup(why
);
2288 i
->who
= strdup(who
);
2290 if (!i
->why
|| !i
->who
) {
2295 fifo_fd
= inhibitor_create_fifo(i
);
2303 return sd_bus_reply_method_return(message
, "h", fifo_fd
);
2312 const sd_bus_vtable manager_vtable
[] = {
2313 SD_BUS_VTABLE_START(0),
2315 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL
, NULL
, offsetof(Manager
, enable_wall_messages
), 0),
2316 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL
, NULL
, offsetof(Manager
, wall_message
), 0),
2318 SD_BUS_PROPERTY("NAutoVTs", "u", NULL
, offsetof(Manager
, n_autovts
), SD_BUS_VTABLE_PROPERTY_CONST
),
2319 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL
, offsetof(Manager
, kill_only_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2320 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL
, offsetof(Manager
, kill_exclude_users
), SD_BUS_VTABLE_PROPERTY_CONST
),
2321 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL
, offsetof(Manager
, kill_user_processes
), SD_BUS_VTABLE_PROPERTY_CONST
),
2322 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
2323 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2324 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2325 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2326 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2327 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
2328 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL
, offsetof(Manager
, inhibit_delay_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
2329 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action
, offsetof(Manager
, handle_power_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2330 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action
, offsetof(Manager
, handle_suspend_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2331 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action
, offsetof(Manager
, handle_hibernate_key
), SD_BUS_VTABLE_PROPERTY_CONST
),
2332 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch
), SD_BUS_VTABLE_PROPERTY_CONST
),
2333 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action
, offsetof(Manager
, handle_lid_switch_docked
), SD_BUS_VTABLE_PROPERTY_CONST
),
2334 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL
, offsetof(Manager
, holdoff_timeout_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2335 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action
, offsetof(Manager
, idle_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
2336 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL
, offsetof(Manager
, idle_action_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
2337 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing
, 0, 0),
2338 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing
, 0, 0),
2339 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown
, 0, 0),
2341 SD_BUS_METHOD("GetSession", "s", "o", method_get_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2342 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2343 SD_BUS_METHOD("GetUser", "u", "o", method_get_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2344 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
2345 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2346 SD_BUS_METHOD("ListSessions", NULL
, "a(susso)", method_list_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2347 SD_BUS_METHOD("ListUsers", NULL
, "a(uso)", method_list_users
, SD_BUS_VTABLE_UNPRIVILEGED
),
2348 SD_BUS_METHOD("ListSeats", NULL
, "a(so)", method_list_seats
, SD_BUS_VTABLE_UNPRIVILEGED
),
2349 SD_BUS_METHOD("ListInhibitors", NULL
, "a(ssssuu)", method_list_inhibitors
, SD_BUS_VTABLE_UNPRIVILEGED
),
2350 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session
, 0),
2351 SD_BUS_METHOD("ReleaseSession", "s", NULL
, method_release_session
, 0),
2352 SD_BUS_METHOD("ActivateSession", "s", NULL
, method_activate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2353 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL
, method_activate_session_on_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2354 SD_BUS_METHOD("LockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2355 SD_BUS_METHOD("UnlockSession", "s", NULL
, method_lock_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2356 SD_BUS_METHOD("LockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2357 SD_BUS_METHOD("UnlockSessions", NULL
, NULL
, method_lock_sessions
, SD_BUS_VTABLE_UNPRIVILEGED
),
2358 SD_BUS_METHOD("KillSession", "ssi", NULL
, method_kill_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2359 SD_BUS_METHOD("KillUser", "ui", NULL
, method_kill_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2360 SD_BUS_METHOD("TerminateSession", "s", NULL
, method_terminate_session
, SD_BUS_VTABLE_UNPRIVILEGED
),
2361 SD_BUS_METHOD("TerminateUser", "u", NULL
, method_terminate_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
2362 SD_BUS_METHOD("TerminateSeat", "s", NULL
, method_terminate_seat
, SD_BUS_VTABLE_UNPRIVILEGED
),
2363 SD_BUS_METHOD("SetUserLinger", "ubb", NULL
, method_set_user_linger
, SD_BUS_VTABLE_UNPRIVILEGED
),
2364 SD_BUS_METHOD("AttachDevice", "ssb", NULL
, method_attach_device
, SD_BUS_VTABLE_UNPRIVILEGED
),
2365 SD_BUS_METHOD("FlushDevices", "b", NULL
, method_flush_devices
, SD_BUS_VTABLE_UNPRIVILEGED
),
2366 SD_BUS_METHOD("PowerOff", "b", NULL
, method_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2367 SD_BUS_METHOD("Reboot", "b", NULL
, method_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2368 SD_BUS_METHOD("Suspend", "b", NULL
, method_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2369 SD_BUS_METHOD("ScheduleShutdown", "st", NULL
, method_schedule_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2370 SD_BUS_METHOD("CancelScheduledShutdown", NULL
, "b", method_cancel_scheduled_shutdown
, SD_BUS_VTABLE_UNPRIVILEGED
),
2371 SD_BUS_METHOD("Hibernate", "b", NULL
, method_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2372 SD_BUS_METHOD("HybridSleep", "b", NULL
, method_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2373 SD_BUS_METHOD("CanPowerOff", NULL
, "s", method_can_poweroff
, SD_BUS_VTABLE_UNPRIVILEGED
),
2374 SD_BUS_METHOD("CanReboot", NULL
, "s", method_can_reboot
, SD_BUS_VTABLE_UNPRIVILEGED
),
2375 SD_BUS_METHOD("CanSuspend", NULL
, "s", method_can_suspend
, SD_BUS_VTABLE_UNPRIVILEGED
),
2376 SD_BUS_METHOD("CanHibernate", NULL
, "s", method_can_hibernate
, SD_BUS_VTABLE_UNPRIVILEGED
),
2377 SD_BUS_METHOD("CanHybridSleep", NULL
, "s", method_can_hybrid_sleep
, SD_BUS_VTABLE_UNPRIVILEGED
),
2378 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit
, SD_BUS_VTABLE_UNPRIVILEGED
),
2379 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL
, "s", method_can_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2380 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL
, method_set_reboot_to_firmware_setup
, SD_BUS_VTABLE_UNPRIVILEGED
),
2382 SD_BUS_SIGNAL("SessionNew", "so", 0),
2383 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2384 SD_BUS_SIGNAL("UserNew", "uo", 0),
2385 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2386 SD_BUS_SIGNAL("SeatNew", "so", 0),
2387 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2388 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2389 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2394 static int session_jobs_reply(Session
*s
, const char *unit
, const char *result
) {
2403 if (streq(result
, "done"))
2404 r
= session_send_create_reply(s
, NULL
);
2406 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
2408 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
2409 r
= session_send_create_reply(s
, &e
);
2415 int match_job_removed(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2416 const char *path
, *result
, *unit
;
2417 Manager
*m
= userdata
;
2427 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
2429 bus_log_parse_error(r
);
2433 if (m
->action_job
&& streq(m
->action_job
, path
)) {
2434 log_info("Operation finished.");
2436 /* Tell people that they now may take a lock again */
2437 send_prepare_for(m
, m
->action_what
, false);
2439 free(m
->action_job
);
2440 m
->action_job
= NULL
;
2441 m
->action_unit
= NULL
;
2446 session
= hashmap_get(m
->session_units
, unit
);
2449 if (streq_ptr(path
, session
->scope_job
)) {
2450 free(session
->scope_job
);
2451 session
->scope_job
= NULL
;
2454 session_jobs_reply(session
, unit
, result
);
2456 session_save(session
);
2457 session_add_to_gc_queue(session
);
2460 user
= hashmap_get(m
->user_units
, unit
);
2463 if (streq_ptr(path
, user
->service_job
)) {
2464 free(user
->service_job
);
2465 user
->service_job
= NULL
;
2468 if (streq_ptr(path
, user
->slice_job
)) {
2469 free(user
->slice_job
);
2470 user
->slice_job
= NULL
;
2473 LIST_FOREACH(sessions_by_user
, session
, user
->sessions
) {
2474 session_jobs_reply(session
, unit
, result
);
2478 user_add_to_gc_queue(user
);
2484 int match_unit_removed(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2485 const char *path
, *unit
;
2486 Manager
*m
= userdata
;
2495 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
2497 bus_log_parse_error(r
);
2501 session
= hashmap_get(m
->session_units
, unit
);
2503 session_add_to_gc_queue(session
);
2505 user
= hashmap_get(m
->user_units
, unit
);
2507 user_add_to_gc_queue(user
);
2512 int match_properties_changed(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2513 _cleanup_free_
char *unit
= NULL
;
2514 Manager
*m
= userdata
;
2524 path
= sd_bus_message_get_path(message
);
2528 r
= unit_name_from_dbus_path(path
, &unit
);
2529 if (r
== -EINVAL
) /* not a unit */
2534 session
= hashmap_get(m
->session_units
, unit
);
2536 session_add_to_gc_queue(session
);
2538 user
= hashmap_get(m
->user_units
, unit
);
2540 user_add_to_gc_queue(user
);
2545 int match_reloading(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2546 Manager
*m
= userdata
;
2553 r
= sd_bus_message_read(message
, "b", &b
);
2555 bus_log_parse_error(r
);
2562 /* systemd finished reloading, let's recheck all our sessions */
2563 log_debug("System manager has been reloaded, rechecking sessions...");
2565 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2566 session_add_to_gc_queue(session
);
2571 int match_name_owner_changed(sd_bus
*bus
, sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
2572 const char *name
, *old
, *new;
2573 Manager
*m
= userdata
;
2581 r
= sd_bus_message_read(message
, "sss", &name
, &old
, &new);
2583 bus_log_parse_error(r
);
2587 if (isempty(old
) || !isempty(new))
2590 key
= set_remove(m
->busnames
, (char*) old
);
2594 /* Drop all controllers owned by this name */
2598 HASHMAP_FOREACH(session
, m
->sessions
, i
)
2599 if (session_is_controller(session
, old
))
2600 session_drop_controller(session
);
2605 int manager_send_changed(Manager
*manager
, const char *property
, ...) {
2610 l
= strv_from_stdarg_alloca(property
);
2612 return sd_bus_emit_properties_changed_strv(
2614 "/org/freedesktop/login1",
2615 "org.freedesktop.login1.Manager",
2619 int manager_start_scope(
2624 const char *description
,
2625 const char *after
, const char *after2
,
2626 sd_bus_error
*error
,
2629 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
2636 r
= sd_bus_message_new_method_call(
2639 "org.freedesktop.systemd1",
2640 "/org/freedesktop/systemd1",
2641 "org.freedesktop.systemd1.Manager",
2642 "StartTransientUnit");
2646 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
2650 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
2654 if (!isempty(slice
)) {
2655 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
2660 if (!isempty(description
)) {
2661 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
2666 if (!isempty(after
)) {
2667 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after
);
2672 if (!isempty(after2
)) {
2673 r
= sd_bus_message_append(m
, "(sv)", "After", "as", 1, after2
);
2678 /* cgroup empty notification is not available in containers
2679 * currently. To make this less problematic, let's shorten the
2680 * stop timeout for sessions, so that we don't wait
2683 /* Make sure that the session shells are terminated with
2684 * SIGHUP since bash and friends tend to ignore SIGTERM */
2685 r
= sd_bus_message_append(m
, "(sv)", "SendSIGHUP", "b", true);
2689 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
2693 r
= sd_bus_message_close_container(m
);
2697 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
2701 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
2709 r
= sd_bus_message_read(reply
, "o", &j
);
2723 int manager_start_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2724 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2730 r
= sd_bus_call_method(
2732 "org.freedesktop.systemd1",
2733 "/org/freedesktop/systemd1",
2734 "org.freedesktop.systemd1.Manager",
2738 "ss", unit
, "fail");
2746 r
= sd_bus_message_read(reply
, "o", &j
);
2760 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
2761 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2767 r
= sd_bus_call_method(
2769 "org.freedesktop.systemd1",
2770 "/org/freedesktop/systemd1",
2771 "org.freedesktop.systemd1.Manager",
2775 "ss", unit
, "fail");
2777 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2778 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
2783 sd_bus_error_free(error
);
2794 r
= sd_bus_message_read(reply
, "o", &j
);
2808 int manager_abandon_scope(Manager
*manager
, const char *scope
, sd_bus_error
*error
) {
2809 _cleanup_free_
char *path
= NULL
;
2815 path
= unit_dbus_path_from_name(scope
);
2819 r
= sd_bus_call_method(
2821 "org.freedesktop.systemd1",
2823 "org.freedesktop.systemd1.Scope",
2829 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2830 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
) ||
2831 sd_bus_error_has_name(error
, BUS_ERROR_SCOPE_NOT_RUNNING
)) {
2832 sd_bus_error_free(error
);
2842 int manager_kill_unit(Manager
*manager
, const char *unit
, KillWho who
, int signo
, sd_bus_error
*error
) {
2846 return sd_bus_call_method(
2848 "org.freedesktop.systemd1",
2849 "/org/freedesktop/systemd1",
2850 "org.freedesktop.systemd1.Manager",
2854 "ssi", unit
, who
== KILL_LEADER
? "main" : "all", signo
);
2857 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
2858 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2859 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2860 _cleanup_free_
char *path
= NULL
;
2867 path
= unit_dbus_path_from_name(unit
);
2871 r
= sd_bus_get_property(
2873 "org.freedesktop.systemd1",
2875 "org.freedesktop.systemd1.Unit",
2881 /* systemd might have droppped off momentarily, let's
2882 * not make this an error */
2883 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
2884 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
2887 /* If the unit is already unloaded then it's not
2889 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
2890 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
2896 r
= sd_bus_message_read(reply
, "s", &state
);
2900 return !streq(state
, "inactive") && !streq(state
, "failed");
2903 int manager_job_is_active(Manager
*manager
, const char *path
) {
2904 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
2905 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
2911 r
= sd_bus_get_property(
2913 "org.freedesktop.systemd1",
2915 "org.freedesktop.systemd1.Job",
2921 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
2922 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
2925 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
2931 /* We don't actually care about the state really. The fact
2932 * that we could read the job state is enough for us */