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"
35 //#include "efivars.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"
47 //#include "special.h"
49 #include "terminal-util.h"
50 #include "udev-util.h"
51 #include "unit-name.h"
52 #include "user-util.h"
53 //#include "utmp-wtmp.h"
55 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
56 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
65 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
69 r = sd_bus_creds_get_session(creds, &name);
74 session = hashmap_get(m->sessions, name);
76 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
82 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
90 if (uid == UID_INVALID) {
91 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
93 /* Note that we get the owner UID of the session, not the actual client UID here! */
94 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
98 r = sd_bus_creds_get_owner_uid(creds, &uid);
103 user = hashmap_get(m->users, UID_TO_PTR(uid));
105 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
111 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
122 r = manager_get_session_from_creds(m, message, NULL, error, &session);
126 seat = session->seat;
129 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
131 seat = hashmap_get(m->seats, name);
133 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
140 static int property_get_idle_hint(
143 const char *interface,
144 const char *property,
145 sd_bus_message *reply,
147 sd_bus_error *error) {
149 Manager *m = userdata;
155 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
158 static int property_get_idle_since_hint(
161 const char *interface,
162 const char *property,
163 sd_bus_message *reply,
165 sd_bus_error *error) {
167 Manager *m = userdata;
168 dual_timestamp t = DUAL_TIMESTAMP_NULL;
174 manager_get_idle_hint(m, &t);
176 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
179 static int property_get_inhibited(
182 const char *interface,
183 const char *property,
184 sd_bus_message *reply,
186 sd_bus_error *error) {
188 Manager *m = userdata;
195 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
197 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
200 static int property_get_preparing(
203 const char *interface,
204 const char *property,
205 sd_bus_message *reply,
207 sd_bus_error *error) {
209 Manager *m = userdata;
216 if (streq(property, "PreparingForShutdown"))
217 b = !!(m->action_what & INHIBIT_SHUTDOWN);
219 b = !!(m->action_what & INHIBIT_SLEEP);
221 return sd_bus_message_append(reply, "b", b);
224 static int property_get_scheduled_shutdown(
227 const char *interface,
228 const char *property,
229 sd_bus_message *reply,
231 sd_bus_error *error) {
233 Manager *m = userdata;
240 r = sd_bus_message_open_container(reply, 'r', "st");
244 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
248 return sd_bus_message_close_container(reply);
251 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
253 static int property_get_docked(
256 const char *interface,
257 const char *property,
258 sd_bus_message *reply,
260 sd_bus_error *error) {
262 Manager *m = userdata;
268 return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
271 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
272 _cleanup_free_ char *p = NULL;
273 Manager *m = userdata;
281 r = sd_bus_message_read(message, "s", &name);
285 r = manager_get_session_from_creds(m, message, name, error, &session);
289 p = session_bus_path(session);
293 return sd_bus_reply_method_return(message, "o", p);
296 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
297 _cleanup_free_ char *p = NULL;
298 Session *session = NULL;
299 Manager *m = userdata;
306 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
308 r = sd_bus_message_read(message, "u", &pid);
315 r = manager_get_session_from_creds(m, message, NULL, error, &session);
319 r = manager_get_session_by_pid(m, pid, &session);
324 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
327 p = session_bus_path(session);
331 return sd_bus_reply_method_return(message, "o", p);
334 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
335 _cleanup_free_ char *p = NULL;
336 Manager *m = userdata;
344 r = sd_bus_message_read(message, "u", &uid);
348 r = manager_get_user_from_creds(m, message, uid, error, &user);
352 p = user_bus_path(user);
356 return sd_bus_reply_method_return(message, "o", p);
359 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
360 _cleanup_free_ char *p = NULL;
361 Manager *m = userdata;
369 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
371 r = sd_bus_message_read(message, "u", &pid);
378 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
382 r = manager_get_user_by_pid(m, pid, &user);
386 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
389 p = user_bus_path(user);
393 return sd_bus_reply_method_return(message, "o", p);
396 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
397 _cleanup_free_ char *p = NULL;
398 Manager *m = userdata;
406 r = sd_bus_message_read(message, "s", &name);
410 r = manager_get_seat_from_creds(m, message, name, error, &seat);
414 p = seat_bus_path(seat);
418 return sd_bus_reply_method_return(message, "o", p);
421 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
422 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
423 Manager *m = userdata;
431 r = sd_bus_message_new_method_return(message, &reply);
435 r = sd_bus_message_open_container(reply, 'a', "(susso)");
439 HASHMAP_FOREACH(session, m->sessions, i) {
440 _cleanup_free_ char *p = NULL;
442 p = session_bus_path(session);
446 r = sd_bus_message_append(reply, "(susso)",
448 (uint32_t) session->user->uid,
450 session->seat ? session->seat->id : "",
456 r = sd_bus_message_close_container(reply);
460 return sd_bus_send(NULL, reply, NULL);
463 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
464 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
465 Manager *m = userdata;
473 r = sd_bus_message_new_method_return(message, &reply);
477 r = sd_bus_message_open_container(reply, 'a', "(uso)");
481 HASHMAP_FOREACH(user, m->users, i) {
482 _cleanup_free_ char *p = NULL;
484 p = user_bus_path(user);
488 r = sd_bus_message_append(reply, "(uso)",
489 (uint32_t) user->uid,
496 r = sd_bus_message_close_container(reply);
500 return sd_bus_send(NULL, reply, NULL);
503 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
504 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
505 Manager *m = userdata;
513 r = sd_bus_message_new_method_return(message, &reply);
517 r = sd_bus_message_open_container(reply, 'a', "(so)");
521 HASHMAP_FOREACH(seat, m->seats, i) {
522 _cleanup_free_ char *p = NULL;
524 p = seat_bus_path(seat);
528 r = sd_bus_message_append(reply, "(so)", seat->id, p);
533 r = sd_bus_message_close_container(reply);
537 return sd_bus_send(NULL, reply, NULL);
540 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
541 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
542 Manager *m = userdata;
543 Inhibitor *inhibitor;
550 r = sd_bus_message_new_method_return(message, &reply);
554 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
558 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
560 r = sd_bus_message_append(reply, "(ssssuu)",
561 strempty(inhibit_what_to_string(inhibitor->what)),
562 strempty(inhibitor->who),
563 strempty(inhibitor->why),
564 strempty(inhibit_mode_to_string(inhibitor->mode)),
565 (uint32_t) inhibitor->uid,
566 (uint32_t) inhibitor->pid);
571 r = sd_bus_message_close_container(reply);
575 return sd_bus_send(NULL, reply, NULL);
578 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
579 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
580 uint32_t audit_id = 0;
581 _cleanup_free_ char *id = NULL;
582 Session *session = NULL;
583 Manager *m = userdata;
597 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
598 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
600 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
604 if (!uid_is_valid(uid))
605 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
606 if (leader < 0 || leader == 1)
607 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
610 t = _SESSION_TYPE_INVALID;
612 t = session_type_from_string(type);
614 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
618 c = _SESSION_CLASS_INVALID;
620 c = session_class_from_string(class);
622 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
625 if (isempty(desktop))
628 if (!string_is_safe(desktop))
629 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
635 seat = hashmap_get(m->seats, cseat);
637 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
640 if (tty_is_vc(tty)) {
645 else if (seat != m->seat0)
646 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
648 v = vtnr_from_tty(tty);
650 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
654 else if (vtnr != (uint32_t) v)
655 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
657 } else if (tty_is_console(tty)) {
661 else if (seat != m->seat0)
662 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
665 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
669 if (seat_has_vts(seat)) {
670 if (!vtnr || vtnr > 63)
671 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
674 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
678 r = sd_bus_message_enter_container(message, 'a', "(sv)");
682 if (t == _SESSION_TYPE_INVALID) {
683 if (!isempty(display))
685 else if (!isempty(tty))
688 t = SESSION_UNSPECIFIED;
691 if (c == _SESSION_CLASS_INVALID) {
692 if (t == SESSION_UNSPECIFIED)
693 c = SESSION_BACKGROUND;
699 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
701 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
705 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
710 r = manager_get_session_by_pid(m, leader, NULL);
712 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
715 * Old gdm and lightdm start the user-session on the same VT as
716 * the greeter session. But they destroy the greeter session
717 * after the user-session and want the user-session to take
718 * over the VT. We need to support this for
719 * backwards-compatibility, so make sure we allow new sessions
720 * on a VT that a greeter is running on. Furthermore, to allow
721 * re-logins, we have to allow a greeter to take over a used VT for
722 * the exact same reasons.
724 if (c != SESSION_GREETER &&
726 vtnr < m->seat0->position_count &&
727 m->seat0->positions[vtnr] &&
728 m->seat0->positions[vtnr]->class != SESSION_GREETER)
729 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
731 audit_session_from_pid(leader, &audit_id);
733 /* Keep our session IDs and the audit session IDs in sync */
735 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
738 /* Wut? There's already a session by this name and we
739 * didn't find it above? Weird, then let's not trust
740 * the audit data and let's better register a new
742 if (hashmap_get(m->sessions, id)) {
743 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
754 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
757 } while (hashmap_get(m->sessions, id));
760 r = manager_add_user_by_uid(m, uid, &user);
764 r = manager_add_session(m, id, &session);
768 session_set_user(session, user);
770 session->leader = leader;
771 session->audit_id = audit_id;
774 session->remote = remote;
775 session->vtnr = vtnr;
778 session->tty = strdup(tty);
785 if (!isempty(display)) {
786 session->display = strdup(display);
787 if (!session->display) {
793 if (!isempty(remote_user)) {
794 session->remote_user = strdup(remote_user);
795 if (!session->remote_user) {
801 if (!isempty(remote_host)) {
802 session->remote_host = strdup(remote_host);
803 if (!session->remote_host) {
809 if (!isempty(service)) {
810 session->service = strdup(service);
811 if (!session->service) {
817 if (!isempty(desktop)) {
818 session->desktop = strdup(desktop);
819 if (!session->desktop) {
826 r = seat_attach_session(seat, session);
831 r = session_start(session);
835 session->create_message = sd_bus_message_ref(message);
837 /* Here upstream systemd starts cgroups and the user systemd,
838 and arranges to reply asynchronously. We reply
841 r = session_send_create_reply(session, NULL);
849 session_add_to_gc_queue(session);
852 user_add_to_gc_queue(user);
857 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
858 Manager *m = userdata;
866 r = sd_bus_message_read(message, "s", &name);
870 r = manager_get_session_from_creds(m, message, name, error, &session);
874 r = session_release(session);
878 session_add_to_gc_queue(session);
880 return sd_bus_reply_method_return(message, NULL);
883 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
884 Manager *m = userdata;
892 r = sd_bus_message_read(message, "s", &name);
896 r = manager_get_session_from_creds(m, message, name, error, &session);
900 return bus_session_method_activate(message, session, error);
903 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
904 const char *session_name, *seat_name;
905 Manager *m = userdata;
913 /* Same as ActivateSession() but refuses to work if
914 * the seat doesn't match */
916 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
920 r = manager_get_session_from_creds(m, message, session_name, error, &session);
924 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
928 if (session->seat != seat)
929 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
931 r = session_activate(session);
935 return sd_bus_reply_method_return(message, NULL);
938 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
939 Manager *m = userdata;
947 r = sd_bus_message_read(message, "s", &name);
951 r = manager_get_session_from_creds(m, message, name, error, &session);
955 return bus_session_method_lock(message, session, error);
958 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
959 Manager *m = userdata;
965 r = bus_verify_polkit_async(
968 "org.freedesktop.login1.lock-sessions",
977 return 1; /* Will call us back */
979 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
983 return sd_bus_reply_method_return(message, NULL);
986 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
988 Manager *m = userdata;
995 r = sd_bus_message_read(message, "s", &name);
999 r = manager_get_session_from_creds(m, message, name, error, &session);
1003 return bus_session_method_kill(message, session, error);
1006 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1007 Manager *m = userdata;
1015 r = sd_bus_message_read(message, "u", &uid);
1019 r = manager_get_user_from_creds(m, message, uid, error, &user);
1023 return bus_user_method_kill(message, user, error);
1026 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1027 Manager *m = userdata;
1035 r = sd_bus_message_read(message, "s", &name);
1039 r = manager_get_session_from_creds(m, message, name, error, &session);
1043 return bus_session_method_terminate(message, session, error);
1046 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1047 Manager *m = userdata;
1055 r = sd_bus_message_read(message, "u", &uid);
1059 r = manager_get_user_from_creds(m, message, uid, error, &user);
1063 return bus_user_method_terminate(message, user, error);
1066 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1067 Manager *m = userdata;
1075 r = sd_bus_message_read(message, "s", &name);
1079 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1083 return bus_seat_method_terminate(message, seat, error);
1086 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1087 _cleanup_free_ char *cc = NULL;
1088 Manager *m = userdata;
1098 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1102 if (uid == UID_INVALID) {
1103 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1105 /* Note that we get the owner UID of the session, not the actual client UID here! */
1106 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1110 r = sd_bus_creds_get_owner_uid(creds, &uid);
1114 } else if (!uid_is_valid(uid))
1120 return errno > 0 ? -errno : -ENOENT;
1122 r = bus_verify_polkit_async(
1125 "org.freedesktop.login1.set-user-linger",
1129 &m->polkit_registry,
1134 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1136 mkdir_p_label("/var/lib/systemd", 0755);
1138 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1142 cc = cescape(pw->pw_name);
1146 path = strjoina("/var/lib/systemd/linger/", cc);
1154 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1161 if (r < 0 && errno != ENOENT)
1164 u = hashmap_get(m->users, UID_TO_PTR(uid));
1166 user_add_to_gc_queue(u);
1169 return sd_bus_reply_method_return(message, NULL);
1172 static int trigger_device(Manager *m, struct udev_device *d) {
1173 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1174 struct udev_list_entry *first, *item;
1179 e = udev_enumerate_new(m->udev);
1184 r = udev_enumerate_add_match_parent(e, d);
1189 r = udev_enumerate_scan_devices(e);
1193 first = udev_enumerate_get_list_entry(e);
1194 udev_list_entry_foreach(item, first) {
1195 _cleanup_free_ char *t = NULL;
1198 p = udev_list_entry_get_name(item);
1200 t = strappend(p, "/uevent");
1204 write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
1210 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1211 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1212 _cleanup_free_ char *rule = NULL, *file = NULL;
1213 const char *id_for_seat;
1220 d = udev_device_new_from_syspath(m->udev, sysfs);
1224 if (!udev_device_has_tag(d, "seat"))
1227 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1231 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1234 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1237 mkdir_p_label("/etc/udev/rules.d", 0755);
1238 r = write_string_file_atomic_label(file, rule);
1242 return trigger_device(m, d);
1245 static int flush_devices(Manager *m) {
1246 _cleanup_closedir_ DIR *d;
1250 d = opendir("/etc/udev/rules.d");
1252 if (errno != ENOENT)
1253 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1257 while ((de = readdir(d))) {
1259 if (!dirent_is_file(de))
1262 if (!startswith(de->d_name, "72-seat-"))
1265 if (!endswith(de->d_name, ".rules"))
1268 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1269 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1273 return trigger_device(m, NULL);
1276 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1277 const char *sysfs, *seat;
1278 Manager *m = userdata;
1284 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1288 if (!path_startswith(sysfs, "/sys"))
1289 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1291 if (!seat_name_is_valid(seat))
1292 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1294 r = bus_verify_polkit_async(
1297 "org.freedesktop.login1.attach-device",
1301 &m->polkit_registry,
1306 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1308 r = attach_device(m, seat, sysfs);
1312 return sd_bus_reply_method_return(message, NULL);
1315 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1316 Manager *m = userdata;
1322 r = sd_bus_message_read(message, "b", &interactive);
1326 r = bus_verify_polkit_async(
1329 "org.freedesktop.login1.flush-devices",
1333 &m->polkit_registry,
1338 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1340 r = flush_devices(m);
1344 return sd_bus_reply_method_return(message, NULL);
1347 static int have_multiple_sessions(
1356 /* Check for other users' sessions. Greeter sessions do not
1357 * count, and non-login sessions do not count either. */
1358 HASHMAP_FOREACH(session, m->sessions, i)
1359 if (session->class == SESSION_USER &&
1360 session->user->uid != uid)
1366 static int bus_manager_log_shutdown(
1369 #if 0 /// elogind does not support systemd units
1370 const char *unit_name) {
1377 if (w != INHIBIT_SHUTDOWN)
1380 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1381 p = "MESSAGE=System is powering down";
1382 q = "SHUTDOWN=power-off";
1383 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1384 p = "MESSAGE=System is halting";
1385 q = "SHUTDOWN=halt";
1386 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1387 p = "MESSAGE=System is rebooting";
1388 q = "SHUTDOWN=reboot";
1389 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1390 p = "MESSAGE=System is rebooting with kexec";
1391 q = "SHUTDOWN=kexec";
1393 p = "MESSAGE=System is shutting down";
1397 HandleAction action) {
1403 if (w != INHIBIT_SHUTDOWN)
1407 case HANDLE_POWEROFF:
1408 p = "MESSAGE=System is powering down.";
1409 q = "SHUTDOWN=power-off";
1412 p = "MESSAGE=System is halting.";
1413 q = "SHUTDOWN=halt";
1416 p = "MESSAGE=System is rebooting.";
1417 q = "SHUTDOWN=reboot";
1420 p = "MESSAGE=System is rebooting with kexec.";
1421 q = "SHUTDOWN=kexec";
1424 p = "MESSAGE=System is shutting down.";
1428 if (isempty(m->wall_message))
1429 p = strjoina(p, ".");
1431 p = strjoina(p, " (", m->wall_message, ").");
1433 return log_struct(LOG_NOTICE,
1434 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1440 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1441 Manager *m = userdata;
1446 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1450 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1455 if (until <= now(CLOCK_MONOTONIC))
1458 /* We want to ignore the lid switch for a while after each
1459 * suspend, and after boot-up. Hence let's install a timer for
1460 * this. As long as the event source exists we ignore the lid
1463 if (m->lid_switch_ignore_event_source) {
1466 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1473 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1475 r = sd_event_add_time(
1477 &m->lid_switch_ignore_event_source,
1480 lid_switch_ignore_handler, m);
1485 static void reset_scheduled_shutdown(Manager *m) {
1486 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1487 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
1488 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
1489 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
1490 m->scheduled_shutdown_timeout = 0;
1491 m->shutdown_dry_run = false;
1493 if (m->unlink_nologin) {
1494 (void) unlink("/run/nologin");
1495 m->unlink_nologin = false;
1499 static int execute_shutdown_or_sleep(
1502 HandleAction action,
1503 sd_bus_error *error) {
1505 #if 0 /// elogind does not need these, we do it ourselves
1506 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1514 assert(w < _INHIBIT_WHAT_MAX);
1516 bus_manager_log_shutdown(m, w, action);
1518 #if 0 /// elogind does it directly without depending on systemd running the system
1519 if (m->shutdown_dry_run) {
1520 log_info("Running in dry run, suppressing action.");
1521 reset_scheduled_shutdown(m);
1523 r = sd_bus_call_method(
1525 "org.freedesktop.systemd1",
1526 "/org/freedesktop/systemd1",
1527 "org.freedesktop.systemd1.Manager",
1531 "ss", NULL, "replace-irreversibly");
1533 r = shutdown_or_sleep(m, action);
1535 /* no more pending actions, whether this failed or not */
1536 m->pending_action = HANDLE_IGNORE;
1542 #if 0 /// elogind neither needs a dbus reply, nor supports systemd action jobs
1543 r = sd_bus_message_read(reply, "o", &p);
1552 m->action_unit = unit_name;
1553 free(m->action_job);
1558 /* Make sure the lid switch is ignored for a while */
1559 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1564 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1566 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1567 Inhibitor *offending = NULL;
1572 if ( (0 == manager->action_what) || (HANDLE_IGNORE == manager->pending_action) )
1575 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1576 _cleanup_free_ char *comm = NULL, *u = NULL;
1581 (void) get_process_comm(offending->pid, &comm);
1582 u = uid_to_name(offending->uid);
1584 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1585 offending->uid, strna(u),
1586 offending->pid, strna(comm));
1589 /* Actually do the operation */
1590 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->pending_action, &error);
1592 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1594 manager->pending_action = HANDLE_IGNORE;
1595 manager->action_what = 0;
1602 static int manager_inhibit_timeout_handler(
1607 Manager *manager = userdata;
1611 assert(manager->inhibit_timeout_source == s);
1613 r = manager_dispatch_delayed(manager, true);
1614 return (r < 0) ? r : 0;
1617 static int delay_shutdown_or_sleep(
1620 HandleAction action) {
1627 assert(w < _INHIBIT_WHAT_MAX);
1629 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1631 if (m->inhibit_timeout_source) {
1632 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1634 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1636 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1638 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1640 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1641 timeout_val, 0, manager_inhibit_timeout_handler, m);
1646 m->pending_action = action;
1652 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1654 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1655 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1656 [INHIBIT_SLEEP] = "PrepareForSleep"
1659 int active = _active;
1663 assert(w < _INHIBIT_WHAT_MAX);
1664 assert(signal_name[w]);
1666 return sd_bus_emit_signal(m->bus,
1667 "/org/freedesktop/login1",
1668 "org.freedesktop.login1.Manager",
1674 int bus_manager_shutdown_or_sleep_now_or_later(
1676 HandleAction action,
1678 sd_bus_error *error) {
1685 assert(w <= _INHIBIT_WHAT_MAX);
1687 /* Tell everybody to prepare for shutdown/sleep */
1688 send_prepare_for(m, w, true);
1691 m->inhibit_delay_max > 0 &&
1692 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1695 /* Shutdown is delayed, keep in mind what we
1696 * want to do, and start a timeout */
1697 r = delay_shutdown_or_sleep(m, w, action);
1699 /* Shutdown is not delayed, execute it
1701 r = execute_shutdown_or_sleep(m, w, action, error);
1706 static int verify_shutdown_creds(
1708 sd_bus_message *message,
1712 const char *action_multiple_sessions,
1713 const char *action_ignore_inhibit,
1714 sd_bus_error *error) {
1716 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1717 bool multiple_sessions, blocked;
1724 assert(w <= _INHIBIT_WHAT_MAX);
1726 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1730 r = sd_bus_creds_get_euid(creds, &uid);
1734 r = have_multiple_sessions(m, uid);
1738 multiple_sessions = r > 0;
1739 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1741 if (multiple_sessions && action_multiple_sessions) {
1742 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1746 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1749 if (blocked && action_ignore_inhibit) {
1750 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1754 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1757 if (!multiple_sessions && !blocked && action) {
1758 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1762 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1768 static int method_do_shutdown_or_sleep(
1770 sd_bus_message *message,
1771 HandleAction sleep_action,
1774 const char *action_multiple_sessions,
1775 const char *action_ignore_inhibit,
1776 const char *sleep_verb,
1777 sd_bus_error *error) {
1784 assert(w <= _INHIBIT_WHAT_MAX);
1786 r = sd_bus_message_read(message, "b", &interactive);
1790 /* Don't allow multiple jobs being executed at the same time */
1792 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1795 r = can_sleep(sleep_verb);
1800 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1803 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1804 action_ignore_inhibit, error);
1808 r = bus_manager_shutdown_or_sleep_now_or_later(m, sleep_action, w, error);
1812 return sd_bus_reply_method_return(message, NULL);
1815 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1816 Manager *m = userdata;
1818 return method_do_shutdown_or_sleep(
1822 "org.freedesktop.login1.power-off",
1823 "org.freedesktop.login1.power-off-multiple-sessions",
1824 "org.freedesktop.login1.power-off-ignore-inhibit",
1829 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1830 Manager *m = userdata;
1832 return method_do_shutdown_or_sleep(
1836 "org.freedesktop.login1.reboot",
1837 "org.freedesktop.login1.reboot-multiple-sessions",
1838 "org.freedesktop.login1.reboot-ignore-inhibit",
1843 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1844 Manager *m = userdata;
1846 return method_do_shutdown_or_sleep(
1850 "org.freedesktop.login1.suspend",
1851 "org.freedesktop.login1.suspend-multiple-sessions",
1852 "org.freedesktop.login1.suspend-ignore-inhibit",
1857 static int nologin_timeout_handler(
1862 Manager *m = userdata;
1865 log_info("Creating /run/nologin, blocking further logins...");
1867 r = write_string_file_atomic_label("/run/nologin", "System is going down.");
1869 log_error_errno(r, "Failed to create /run/nologin: %m");
1871 m->unlink_nologin = true;
1876 static int update_schedule_file(Manager *m) {
1877 _cleanup_free_ char *temp_path = NULL;
1878 _cleanup_fclose_ FILE *f = NULL;
1883 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1885 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1887 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1889 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1891 (void) fchmod(fileno(f), 0644);
1897 m->scheduled_shutdown_timeout,
1898 m->enable_wall_messages,
1899 m->scheduled_shutdown_type);
1901 if (!isempty(m->wall_message)) {
1902 _cleanup_free_ char *t;
1904 t = cescape(m->wall_message);
1910 fprintf(f, "WALL_MESSAGE=%s\n", t);
1913 r = fflush_and_check(f);
1917 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1925 (void) unlink(temp_path);
1926 (void) unlink("/run/systemd/shutdown/scheduled");
1928 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
1931 static int manager_scheduled_shutdown_handler(
1936 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1937 Manager *m = userdata;
1938 HandleAction action;
1943 if (isempty(m->scheduled_shutdown_type))
1946 if (streq(m->scheduled_shutdown_type, "halt"))
1947 action = HANDLE_HALT;
1948 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1949 action = HANDLE_POWEROFF;
1951 action = HANDLE_REBOOT;
1953 r = execute_shutdown_or_sleep(m, 0, action, &error);
1955 return log_error_errno(r, "Unable to execute transition to %s: %m", m->scheduled_shutdown_type);
1960 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1961 Manager *m = userdata;
1962 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1963 const char *action_multiple_sessions = NULL;
1964 const char *action_ignore_inhibit = NULL;
1965 const char *action = NULL;
1973 r = sd_bus_message_read(message, "st", &type, &elapse);
1977 if (startswith(type, "dry-")) {
1979 m->shutdown_dry_run = true;
1982 if (streq(type, "reboot")) {
1983 action = "org.freedesktop.login1.reboot";
1984 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1985 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1986 } else if (streq(type, "halt")) {
1987 action = "org.freedesktop.login1.halt";
1988 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1989 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1990 } else if (streq(type, "poweroff")) {
1991 action = "org.freedesktop.login1.power-off";
1992 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
1993 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
1995 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1997 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1998 action, action_multiple_sessions, action_ignore_inhibit, error);
2002 if (m->scheduled_shutdown_timeout_source) {
2003 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2005 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2007 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2009 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2011 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2012 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2014 return log_error_errno(r, "sd_event_add_time() failed: %m");
2017 r = free_and_strdup(&m->scheduled_shutdown_type, type);
2019 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2023 if (m->nologin_timeout_source) {
2024 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2026 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2028 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2030 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2032 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2033 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2035 return log_error_errno(r, "sd_event_add_time() failed: %m");
2038 m->scheduled_shutdown_timeout = elapse;
2040 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2042 const char *tty = NULL;
2044 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2045 (void) sd_bus_creds_get_tty(creds, &tty);
2047 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2049 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2054 #if 0 /// elogind does not support utmp-wtmp
2055 r = manager_setup_wall_message_timer(m);
2060 if (!isempty(type)) {
2061 r = update_schedule_file(m);
2065 (void) unlink("/run/systemd/shutdown/scheduled");
2067 return sd_bus_reply_method_return(message, NULL);
2070 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2071 Manager *m = userdata;
2077 cancelled = m->scheduled_shutdown_type != NULL;
2078 reset_scheduled_shutdown(m);
2080 #if 0 /// elogind does not support utmp-wtmp
2082 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2083 const char *tty = NULL;
2087 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2089 (void) sd_bus_creds_get_uid(creds, &uid);
2090 (void) sd_bus_creds_get_tty(creds, &tty);
2093 utmp_wall("The system shutdown has been cancelled",
2094 uid_to_name(uid), tty, logind_wall_tty_filter, m);
2098 return sd_bus_reply_method_return(message, "b", cancelled);
2101 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2102 Manager *m = userdata;
2104 return method_do_shutdown_or_sleep(
2108 "org.freedesktop.login1.hibernate",
2109 "org.freedesktop.login1.hibernate-multiple-sessions",
2110 "org.freedesktop.login1.hibernate-ignore-inhibit",
2115 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2116 Manager *m = userdata;
2118 return method_do_shutdown_or_sleep(
2120 HANDLE_HYBRID_SLEEP,
2122 "org.freedesktop.login1.hibernate",
2123 "org.freedesktop.login1.hibernate-multiple-sessions",
2124 "org.freedesktop.login1.hibernate-ignore-inhibit",
2129 static int method_can_shutdown_or_sleep(
2131 sd_bus_message *message,
2134 const char *action_multiple_sessions,
2135 const char *action_ignore_inhibit,
2136 const char *sleep_verb,
2137 sd_bus_error *error) {
2139 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2140 bool multiple_sessions, challenge, blocked;
2141 const char *result = NULL;
2148 assert(w <= _INHIBIT_WHAT_MAX);
2150 assert(action_multiple_sessions);
2151 assert(action_ignore_inhibit);
2154 r = can_sleep(sleep_verb);
2158 return sd_bus_reply_method_return(message, "s", "na");
2161 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2165 r = sd_bus_creds_get_euid(creds, &uid);
2169 r = have_multiple_sessions(m, uid);
2173 multiple_sessions = r > 0;
2174 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2176 if (multiple_sessions) {
2177 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2184 result = "challenge";
2190 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2194 if (r > 0 && !result)
2196 else if (challenge && (!result || streq(result, "yes")))
2197 result = "challenge";
2202 if (!multiple_sessions && !blocked) {
2203 /* If neither inhibit nor multiple sessions
2204 * apply then just check the normal policy */
2206 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2213 result = "challenge";
2218 return sd_bus_reply_method_return(message, "s", result);
2221 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2222 Manager *m = userdata;
2224 return method_can_shutdown_or_sleep(
2227 "org.freedesktop.login1.power-off",
2228 "org.freedesktop.login1.power-off-multiple-sessions",
2229 "org.freedesktop.login1.power-off-ignore-inhibit",
2234 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2235 Manager *m = userdata;
2237 return method_can_shutdown_or_sleep(
2240 "org.freedesktop.login1.reboot",
2241 "org.freedesktop.login1.reboot-multiple-sessions",
2242 "org.freedesktop.login1.reboot-ignore-inhibit",
2247 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2248 Manager *m = userdata;
2250 return method_can_shutdown_or_sleep(
2253 "org.freedesktop.login1.suspend",
2254 "org.freedesktop.login1.suspend-multiple-sessions",
2255 "org.freedesktop.login1.suspend-ignore-inhibit",
2260 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2261 Manager *m = userdata;
2263 return method_can_shutdown_or_sleep(
2266 "org.freedesktop.login1.hibernate",
2267 "org.freedesktop.login1.hibernate-multiple-sessions",
2268 "org.freedesktop.login1.hibernate-ignore-inhibit",
2273 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2274 Manager *m = userdata;
2276 return method_can_shutdown_or_sleep(
2279 "org.freedesktop.login1.hibernate",
2280 "org.freedesktop.login1.hibernate-multiple-sessions",
2281 "org.freedesktop.login1.hibernate-ignore-inhibit",
2286 static int property_get_reboot_to_firmware_setup(
2289 const char *interface,
2290 const char *property,
2291 sd_bus_message *reply,
2293 sd_bus_error *error) {
2294 #if 0 /// elogind does not support EFI
2301 r = efi_get_reboot_to_firmware();
2302 if (r < 0 && r != -EOPNOTSUPP)
2305 return sd_bus_message_append(reply, "b", r > 0);
2307 return sd_bus_message_append(reply, "b", -EOPNOTSUPP);
2311 static int method_set_reboot_to_firmware_setup(
2312 sd_bus_message *message,
2314 sd_bus_error *error) {
2317 Manager *m = userdata;
2322 r = sd_bus_message_read(message, "b", &b);
2326 r = bus_verify_polkit_async(message,
2328 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2332 &m->polkit_registry,
2337 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2339 #if 0 /// elogind does not support EFI
2340 r = efi_set_reboot_to_firmware(b);
2345 return sd_bus_reply_method_return(message, NULL);
2348 static int method_can_reboot_to_firmware_setup(
2349 sd_bus_message *message,
2351 sd_bus_error *error) {
2353 #if 0 /// elogind does not support EFI
2357 Manager *m = userdata;
2362 r = efi_reboot_to_firmware_supported();
2363 if (r == -EOPNOTSUPP)
2364 return sd_bus_reply_method_return(message, "s", "na");
2368 r = bus_test_polkit(message,
2370 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2381 result = "challenge";
2385 return sd_bus_reply_method_return(message, "s", result);
2387 return sd_bus_reply_method_return(message, "s", "na");
2391 static int method_set_wall_message(
2392 sd_bus_message *message,
2394 sd_bus_error *error) {
2397 Manager *m = userdata;
2399 int enable_wall_messages;
2404 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2408 r = bus_verify_polkit_async(message,
2410 "org.freedesktop.login1.set-wall-message",
2414 &m->polkit_registry,
2419 return 1; /* Will call us back */
2421 if (isempty(wall_message))
2422 m->wall_message = mfree(m->wall_message);
2424 r = free_and_strdup(&m->wall_message, wall_message);
2429 m->enable_wall_messages = enable_wall_messages;
2431 return sd_bus_reply_method_return(message, NULL);
2434 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2435 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2436 const char *who, *why, *what, *mode;
2437 _cleanup_free_ char *id = NULL;
2438 _cleanup_close_ int fifo_fd = -1;
2439 Manager *m = userdata;
2440 Inhibitor *i = NULL;
2450 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2454 w = inhibit_what_from_string(what);
2456 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2458 mm = inhibit_mode_from_string(mode);
2460 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2462 /* Delay is only supported for shutdown/sleep */
2463 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2464 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2466 /* Don't allow taking delay locks while we are already
2467 * executing the operation. We shouldn't create the impression
2468 * that the lock was successful if the machine is about to go
2469 * down/suspend any moment. */
2470 if (m->action_what & w)
2471 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2473 r = bus_verify_polkit_async(
2476 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2477 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2478 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2479 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2480 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2481 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2482 "org.freedesktop.login1.inhibit-handle-lid-switch",
2486 &m->polkit_registry,
2491 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2493 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2497 r = sd_bus_creds_get_euid(creds, &uid);
2501 r = sd_bus_creds_get_pid(creds, &pid);
2508 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2511 } while (hashmap_get(m->inhibitors, id));
2513 r = manager_add_inhibitor(m, id, &i);
2521 i->why = strdup(why);
2522 i->who = strdup(who);
2524 if (!i->why || !i->who) {
2529 fifo_fd = inhibitor_create_fifo(i);
2537 return sd_bus_reply_method_return(message, "h", fifo_fd);
2546 const sd_bus_vtable manager_vtable[] = {
2547 SD_BUS_VTABLE_START(0),
2549 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2550 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2552 // SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2553 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2554 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2555 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2556 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2557 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2558 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2559 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2560 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2561 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2562 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2563 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2564 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2565 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2566 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2567 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2568 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2569 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2570 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2571 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2572 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2573 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2574 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2576 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2577 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2578 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2579 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2580 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2581 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2582 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2583 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2584 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2585 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2586 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2587 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2588 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2589 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2590 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2591 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2592 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2593 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2594 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2595 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2596 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2597 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2598 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2599 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2600 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2601 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2602 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2603 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2604 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2605 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2606 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2607 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2608 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2609 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2610 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2611 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2612 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2613 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2614 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2615 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2616 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2618 SD_BUS_SIGNAL("SessionNew", "so", 0),
2619 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2620 SD_BUS_SIGNAL("UserNew", "uo", 0),
2621 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2622 SD_BUS_SIGNAL("SeatNew", "so", 0),
2623 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2624 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2625 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2630 #if 0 /// UNNEEDED by elogind
2631 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2640 if (streq(result, "done"))
2641 r = session_send_create_reply(s, NULL);
2643 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2645 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2646 r = session_send_create_reply(s, &e);
2652 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2653 const char *path, *result, *unit;
2654 Manager *m = userdata;
2663 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2665 bus_log_parse_error(r);
2669 if (m->action_job && streq(m->action_job, path)) {
2670 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2672 /* Tell people that they now may take a lock again */
2673 send_prepare_for(m, m->action_what, false);
2675 m->action_job = mfree(m->action_job);
2676 m->action_unit = NULL;
2681 session = hashmap_get(m->session_units, unit);
2682 if (session && streq_ptr(path, session->scope_job)) {
2683 session->scope_job = mfree(session->scope_job);
2684 session_jobs_reply(session, unit, result);
2686 session_save(session);
2687 user_save(session->user);
2688 session_add_to_gc_queue(session);
2691 user = hashmap_get(m->user_units, unit);
2693 (streq_ptr(path, user->service_job) ||
2694 streq_ptr(path, user->slice_job))) {
2696 if (streq_ptr(path, user->service_job))
2697 user->service_job = mfree(user->service_job);
2699 if (streq_ptr(path, user->slice_job))
2700 user->slice_job = mfree(user->slice_job);
2702 LIST_FOREACH(sessions_by_user, session, user->sessions)
2703 session_jobs_reply(session, unit, result);
2706 user_add_to_gc_queue(user);
2712 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2713 const char *path, *unit;
2714 Manager *m = userdata;
2722 r = sd_bus_message_read(message, "so", &unit, &path);
2724 bus_log_parse_error(r);
2728 session = hashmap_get(m->session_units, unit);
2730 session_add_to_gc_queue(session);
2732 user = hashmap_get(m->user_units, unit);
2734 user_add_to_gc_queue(user);
2739 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2740 _cleanup_free_ char *unit = NULL;
2741 Manager *m = userdata;
2750 path = sd_bus_message_get_path(message);
2754 r = unit_name_from_dbus_path(path, &unit);
2755 if (r == -EINVAL) /* not a unit */
2762 session = hashmap_get(m->session_units, unit);
2764 session_add_to_gc_queue(session);
2766 user = hashmap_get(m->user_units, unit);
2768 user_add_to_gc_queue(user);
2773 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2774 Manager *m = userdata;
2782 r = sd_bus_message_read(message, "b", &b);
2784 bus_log_parse_error(r);
2791 /* systemd finished reloading, let's recheck all our sessions */
2792 log_debug("System manager has been reloaded, rechecking sessions...");
2794 HASHMAP_FOREACH(session, m->sessions, i)
2795 session_add_to_gc_queue(session);
2801 int manager_send_changed(Manager *manager, const char *property, ...) {
2806 l = strv_from_stdarg_alloca(property);
2808 return sd_bus_emit_properties_changed_strv(
2810 "/org/freedesktop/login1",
2811 "org.freedesktop.login1.Manager",
2815 #if 0 /// UNNEEDED by elogind
2816 int manager_start_slice(
2819 const char *description,
2823 sd_bus_error *error,
2826 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2832 r = sd_bus_message_new_method_call(
2835 "org.freedesktop.systemd1",
2836 "/org/freedesktop/systemd1",
2837 "org.freedesktop.systemd1.Manager",
2838 "StartTransientUnit");
2842 r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
2846 r = sd_bus_message_open_container(m, 'a', "(sv)");
2850 if (!isempty(description)) {
2851 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2856 if (!isempty(after)) {
2857 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2862 if (!isempty(after2)) {
2863 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2868 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
2872 r = sd_bus_message_close_container(m);
2876 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2880 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2888 r = sd_bus_message_read(reply, "o", &j);
2902 int manager_start_scope(
2907 const char *description,
2911 sd_bus_error *error,
2914 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2921 r = sd_bus_message_new_method_call(
2924 "org.freedesktop.systemd1",
2925 "/org/freedesktop/systemd1",
2926 "org.freedesktop.systemd1.Manager",
2927 "StartTransientUnit");
2931 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2935 r = sd_bus_message_open_container(m, 'a', "(sv)");
2939 if (!isempty(slice)) {
2940 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2945 if (!isempty(description)) {
2946 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2951 if (!isempty(after)) {
2952 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2957 if (!isempty(after2)) {
2958 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2963 /* cgroup empty notification is not available in containers
2964 * currently. To make this less problematic, let's shorten the
2965 * stop timeout for sessions, so that we don't wait
2968 /* Make sure that the session shells are terminated with
2969 * SIGHUP since bash and friends tend to ignore SIGTERM */
2970 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2974 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2978 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
2982 r = sd_bus_message_close_container(m);
2986 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2990 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2998 r = sd_bus_message_read(reply, "o", &j);
3012 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3013 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3019 r = sd_bus_call_method(
3021 "org.freedesktop.systemd1",
3022 "/org/freedesktop/systemd1",
3023 "org.freedesktop.systemd1.Manager",
3027 "ss", unit, "replace");
3035 r = sd_bus_message_read(reply, "o", &j);
3049 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3050 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3056 r = sd_bus_call_method(
3058 "org.freedesktop.systemd1",
3059 "/org/freedesktop/systemd1",
3060 "org.freedesktop.systemd1.Manager",
3064 "ss", unit, "fail");
3066 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3067 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3072 sd_bus_error_free(error);
3083 r = sd_bus_message_read(reply, "o", &j);
3097 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3098 _cleanup_free_ char *path = NULL;
3104 path = unit_dbus_path_from_name(scope);
3108 r = sd_bus_call_method(
3110 "org.freedesktop.systemd1",
3112 "org.freedesktop.systemd1.Scope",
3118 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3119 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3120 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3121 sd_bus_error_free(error);
3131 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3135 return sd_bus_call_method(
3137 "org.freedesktop.systemd1",
3138 "/org/freedesktop/systemd1",
3139 "org.freedesktop.systemd1.Manager",
3143 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3146 int manager_unit_is_active(Manager *manager, const char *unit) {
3147 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3148 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3149 _cleanup_free_ char *path = NULL;
3156 path = unit_dbus_path_from_name(unit);
3160 r = sd_bus_get_property(
3162 "org.freedesktop.systemd1",
3164 "org.freedesktop.systemd1.Unit",
3170 /* systemd might have droppped off momentarily, let's
3171 * not make this an error */
3172 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3173 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3176 /* If the unit is already unloaded then it's not
3178 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3179 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3185 r = sd_bus_message_read(reply, "s", &state);
3189 return !streq(state, "inactive") && !streq(state, "failed");
3192 int manager_job_is_active(Manager *manager, const char *path) {
3193 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3194 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3200 r = sd_bus_get_property(
3202 "org.freedesktop.systemd1",
3204 "org.freedesktop.systemd1.Job",
3210 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3211 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3214 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3220 /* We don't actually care about the state really. The fact
3221 * that we could read the job state is enough for us */