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/>.
28 #include "sd-messages.h"
31 #include "path-util.h"
33 #include "sleep-config.h"
34 #include "fileio-label.h"
37 #include "unit-name.h"
41 #include "bus-error.h"
44 static int property_get_idle_hint(
47 const char *interface,
49 sd_bus_message *reply,
53 Manager *m = userdata;
59 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
62 static int property_get_idle_since_hint(
65 const char *interface,
67 sd_bus_message *reply,
71 Manager *m = userdata;
78 manager_get_idle_hint(m, &t);
80 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
83 static int property_get_inhibited(
86 const char *interface,
88 sd_bus_message *reply,
92 Manager *m = userdata;
99 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
101 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
104 static int property_get_preparing(
107 const char *interface,
108 const char *property,
109 sd_bus_message *reply,
113 Manager *m = userdata;
120 if (streq(property, "PreparingForShutdown"))
121 b = !!(m->action_what & INHIBIT_SHUTDOWN);
123 b = !!(m->action_what & INHIBIT_SLEEP);
125 return sd_bus_message_append(reply, "b", b);
128 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
130 static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
131 _cleanup_free_ char *p = NULL;
132 Manager *m = userdata;
141 r = sd_bus_message_read(message, "s", &name);
143 return sd_bus_reply_method_errno(bus, message, r, NULL);
145 session = hashmap_get(m->sessions, name);
147 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
149 p = session_bus_path(session);
151 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
153 return sd_bus_reply_method_return(bus, message, "o", p);
156 static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata) {
157 _cleanup_free_ char *p = NULL;
158 Session *session = NULL;
159 Manager *m = userdata;
167 r = sd_bus_message_read(message, "u", &pid);
169 return sd_bus_reply_method_errno(bus, message, r, NULL);
171 r = manager_get_session_by_pid(m, pid, &session);
173 return sd_bus_reply_method_errno(bus, message, r, NULL);
175 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SESSION_FOR_PID, "PID %lu does not belong to any known session", (unsigned long) pid);
177 p = session_bus_path(session);
179 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
181 return sd_bus_reply_method_return(bus, message, "o", p);
184 static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata) {
185 _cleanup_free_ char *p = NULL;
186 Manager *m = userdata;
195 r = sd_bus_message_read(message, "u", &uid);
197 return sd_bus_reply_method_errno(bus, message, r, NULL);
199 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
201 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_USER, "No user '%lu' known or logged in", (unsigned long) uid);
203 p = user_bus_path(user);
205 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
207 return sd_bus_reply_method_return(bus, message, "o", p);
210 static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata) {
211 _cleanup_free_ char *p = NULL;
212 Manager *m = userdata;
221 r = sd_bus_message_read(message, "u", &pid);
223 return sd_bus_reply_method_errno(bus, message, r, NULL);
225 r = manager_get_user_by_pid(m, pid, &user);
227 return sd_bus_reply_method_errno(bus, message, r, NULL);
229 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_USER_FOR_PID, "PID %lu does not belong to any known or logged in user", (unsigned long) pid);
231 p = user_bus_path(user);
233 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
235 return sd_bus_reply_method_return(bus, message, "o", p);
238 static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata) {
239 _cleanup_free_ char *p = NULL;
240 Manager *m = userdata;
249 r = sd_bus_message_read(message, "s", &name);
251 return sd_bus_reply_method_errno(bus, message, r, NULL);
253 seat = hashmap_get(m->seats, name);
255 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
257 p = seat_bus_path(seat);
259 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
261 return sd_bus_reply_method_return(bus, message, "o", p);
264 static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata) {
265 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
266 Manager *m = userdata;
275 r = sd_bus_message_new_method_return(bus, message, &reply);
277 return sd_bus_reply_method_errno(bus, message, r, NULL);
279 r = sd_bus_message_open_container(reply, 'a', "(susso)");
281 return sd_bus_reply_method_errno(bus, message, r, NULL);
283 HASHMAP_FOREACH(session, m->sessions, i) {
284 _cleanup_free_ char *p = NULL;
286 p = session_bus_path(session);
288 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
290 r = sd_bus_message_append(reply, "(susso)",
292 (uint32_t) session->user->uid,
294 session->seat ? session->seat->id : "",
297 return sd_bus_reply_method_errno(bus, message, r, NULL);
300 r = sd_bus_message_close_container(reply);
302 return sd_bus_reply_method_errno(bus, message, r, NULL);
304 return sd_bus_send(bus, reply, NULL);
307 static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata) {
308 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
309 Manager *m = userdata;
318 r = sd_bus_message_new_method_return(bus, message, &reply);
320 return sd_bus_reply_method_errno(bus, message, r, NULL);
322 r = sd_bus_message_open_container(reply, 'a', "(uso)");
324 return sd_bus_reply_method_errno(bus, message, r, NULL);
326 HASHMAP_FOREACH(user, m->users, i) {
327 _cleanup_free_ char *p = NULL;
329 p = user_bus_path(user);
331 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
333 r = sd_bus_message_append(reply, "(uso)",
334 (uint32_t) user->uid,
338 return sd_bus_reply_method_errno(bus, message, r, NULL);
341 r = sd_bus_message_close_container(reply);
343 return sd_bus_reply_method_errno(bus, message, r, NULL);
345 return sd_bus_send(bus, reply, NULL);
348 static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata) {
349 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
350 Manager *m = userdata;
359 r = sd_bus_message_new_method_return(bus, message, &reply);
361 return sd_bus_reply_method_errno(bus, message, r, NULL);
363 r = sd_bus_message_open_container(reply, 'a', "(so)");
365 return sd_bus_reply_method_errno(bus, message, r, NULL);
367 HASHMAP_FOREACH(seat, m->seats, i) {
368 _cleanup_free_ char *p = NULL;
370 p = seat_bus_path(seat);
372 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
374 r = sd_bus_message_append(reply, "(so)", seat->id, p);
376 return sd_bus_reply_method_errno(bus, message, r, NULL);
379 r = sd_bus_message_close_container(reply);
381 return sd_bus_reply_method_errno(bus, message, r, NULL);
383 return sd_bus_send(bus, reply, NULL);
386 static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata) {
387 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
388 Manager *m = userdata;
389 Inhibitor *inhibitor;
393 r = sd_bus_message_new_method_return(bus, message, &reply);
395 return sd_bus_reply_method_errno(bus, message, r, NULL);
397 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
399 return sd_bus_reply_method_errno(bus, message, r, NULL);
401 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
403 r = sd_bus_message_append(reply, "ssssuu",
404 strempty(inhibit_what_to_string(inhibitor->what)),
405 strempty(inhibitor->who),
406 strempty(inhibitor->why),
407 strempty(inhibit_mode_to_string(inhibitor->mode)),
408 (uint32_t) inhibitor->uid,
409 (uint32_t) inhibitor->pid);
411 return sd_bus_reply_method_errno(bus, message, r, NULL);
414 r = sd_bus_message_close_container(reply);
416 return sd_bus_reply_method_errno(bus, message, r, NULL);
418 return sd_bus_send(bus, reply, NULL);
421 static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
422 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host;
423 uint32_t uid, leader, audit_id = 0;
424 _cleanup_free_ char *id = NULL;
425 Session *session = NULL;
426 Manager *m = userdata;
439 r = sd_bus_message_read(message, "uussssussbss", &uid, &leader, &service, &type, &class, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
441 return sd_bus_reply_method_errno(bus, message, r, NULL);
444 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
447 t = _SESSION_TYPE_INVALID;
449 t = session_type_from_string(type);
451 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
455 c = _SESSION_CLASS_INVALID;
457 c = session_class_from_string(class);
459 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
465 seat = hashmap_get(m->seats, cseat);
467 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", seat);
470 if (tty_is_vc(tty)) {
475 else if (seat != m->seat0)
476 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat);
478 v = vtnr_from_tty(tty);
480 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
484 else if (vtnr != (uint32_t) v)
485 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
487 } else if (tty_is_console(tty)) {
491 else if (seat != m->seat0)
492 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
495 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
499 if (seat_has_vts(seat)) {
501 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
504 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
508 r = sd_bus_message_enter_container(message, 'a', "(sv)");
510 return sd_bus_reply_method_errno(bus, message, r, NULL);
512 if (t == _SESSION_TYPE_INVALID) {
513 if (!isempty(display))
515 else if (!isempty(tty))
518 t = SESSION_UNSPECIFIED;
521 if (c == _SESSION_CLASS_INVALID) {
522 if (!isempty(display) || !isempty(tty))
525 c = SESSION_BACKGROUND;
529 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
531 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), (pid_t*) &leader);
533 return sd_bus_reply_method_errno(bus, message, r, NULL);
536 manager_get_session_by_pid(m, leader, &session);
538 _cleanup_free_ char *path = NULL;
539 _cleanup_close_ int fifo_fd = -1;
541 /* Session already exists, client is probably
542 * something like "su" which changes uid but is still
543 * the same session */
545 fifo_fd = session_create_fifo(session);
547 return sd_bus_reply_method_errno(bus, message, fifo_fd, NULL);
549 path = session_bus_path(session);
551 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
553 return sd_bus_reply_method_return(
554 bus, message, "soshsub",
557 session->user->runtime_path,
559 session->seat ? session->seat->id : "",
560 (uint32_t) session->vtnr,
564 audit_session_from_pid(leader, &audit_id);
566 /* Keep our session IDs and the audit session IDs in sync */
568 if (asprintf(&id, "%lu", (unsigned long) audit_id) < 0)
569 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
571 /* Wut? There's already a session by this name and we
572 * didn't find it above? Weird, then let's not trust
573 * the audit data and let's better register a new
575 if (hashmap_get(m->sessions, id)) {
576 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
589 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
590 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
592 } while (hashmap_get(m->sessions, id));
595 r = manager_add_user_by_uid(m, uid, &user);
597 r = sd_bus_reply_method_errno(bus, message, r, NULL);
601 r = manager_add_session(m, id, &session);
603 r = sd_bus_reply_method_errno(bus, message, r, NULL);
607 session_set_user(session, user);
609 session->leader = leader;
610 session->audit_id = audit_id;
613 session->remote = remote;
614 session->vtnr = vtnr;
617 session->tty = strdup(tty);
619 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
624 if (!isempty(display)) {
625 session->display = strdup(display);
626 if (!session->display) {
627 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
632 if (!isempty(remote_user)) {
633 session->remote_user = strdup(remote_user);
634 if (!session->remote_user) {
635 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
640 if (!isempty(remote_host)) {
641 session->remote_host = strdup(remote_host);
642 if (!session->remote_host) {
643 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
648 if (!isempty(service)) {
649 session->service = strdup(service);
650 if (!session->service) {
651 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
657 r = seat_attach_session(seat, session);
659 r = sd_bus_reply_method_errno(bus, message, r, NULL);
664 r = session_start(session);
666 r = sd_bus_reply_method_errno(bus, message, r, NULL);
670 session->create_message = sd_bus_message_ref(message);
672 /* Now, let's wait until the slice unit and stuff got
673 * created. We send the reply back from
674 * session_send_create_reply().*/
680 session_add_to_gc_queue(session);
683 user_add_to_gc_queue(user);
688 static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
689 Manager *m = userdata;
698 r = sd_bus_message_read(message, "s", &name);
700 return sd_bus_reply_method_errno(bus, message, r, NULL);
702 session = hashmap_get(m->sessions, name);
704 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
706 /* We use the FIFO to detect stray sessions where the process
707 invoking PAM dies abnormally. We need to make sure that
708 that process is not killed if at the clean end of the
709 session it closes the FIFO. Hence, with this call
710 explicitly turn off the FIFO logic, so that the PAM code
711 can finish clean up on its own */
712 session_remove_fifo(session);
713 session_save(session);
714 user_save(session->user);
716 return sd_bus_reply_method_return(bus, message, NULL);
719 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
720 Manager *m = userdata;
729 r = sd_bus_message_read(message, "s", &name);
731 return sd_bus_reply_method_errno(bus, message, r, NULL);
733 session = hashmap_get(m->sessions, name);
735 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
737 r = session_activate(session);
739 return sd_bus_reply_method_errno(bus, message, r, NULL);
741 return sd_bus_reply_method_return(bus, message, NULL);
744 static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata) {
745 const char *session_name, *seat_name;
746 Manager *m = userdata;
755 /* Same as ActivateSession() but refuses to work if
756 * the seat doesn't match */
758 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
760 return sd_bus_reply_method_errno(bus, message, r, NULL);
762 session = hashmap_get(m->sessions, session_name);
764 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", session_name);
766 seat = hashmap_get(m->seats, seat_name);
768 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", seat_name);
770 if (session->seat != seat)
771 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
773 r = session_activate(session);
775 return sd_bus_reply_method_errno(bus, message, r, NULL);
777 return sd_bus_reply_method_return(bus, message, NULL);
780 static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
781 Manager *m = userdata;
790 r = sd_bus_message_read(message, "s", &name);
792 return sd_bus_reply_method_errno(bus, message, r, NULL);
794 session = hashmap_get(m->sessions, name);
796 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
798 r = session_send_lock(session, streq(sd_bus_message_get_member(message), "LockSession"));
800 return sd_bus_reply_method_errno(bus, message, r, NULL);
802 return sd_bus_reply_method_return(bus, message, NULL);
805 static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata) {
806 Manager *m = userdata;
813 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
815 return sd_bus_reply_method_errno(bus, message, r, NULL);
817 return sd_bus_reply_method_return(bus, message, NULL);
820 static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
821 const char *name, *swho;
822 Manager *m = userdata;
832 r = sd_bus_message_read(message, "ssi", &name, &swho, &signo);
834 return sd_bus_reply_method_errno(bus, message, r, NULL);
839 who = kill_who_from_string(swho);
841 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
844 if (signo <= 0 || signo >= _NSIG)
845 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
847 session = hashmap_get(m->sessions, name);
849 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
851 r = session_kill(session, who, signo);
853 return sd_bus_reply_method_errno(bus, message, r, NULL);
855 return sd_bus_reply_method_return(bus, message, NULL);
858 static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata) {
859 Manager *m = userdata;
869 r = sd_bus_message_read(message, "ui", &uid, &signo);
871 return sd_bus_reply_method_errno(bus, message, r, NULL);
873 if (signo <= 0 || signo >= _NSIG)
874 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
876 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
878 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_USER, "No user '%lu' known or logged in", (unsigned long) uid);
880 r = user_kill(user, signo);
882 return sd_bus_reply_method_errno(bus, message, r, NULL);
884 return sd_bus_reply_method_return(bus, message, NULL);
887 static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
888 Manager *m = userdata;
897 r = sd_bus_message_read(message, "s", &name);
899 return sd_bus_reply_method_errno(bus, message, r, NULL);
901 session = hashmap_get(m->sessions, name);
903 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
905 r = session_stop(session);
907 return sd_bus_reply_method_errno(bus, message, r, NULL);
909 return sd_bus_reply_method_return(bus, message, NULL);
912 static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata) {
913 Manager *m = userdata;
922 r = sd_bus_message_read(message, "u", &uid);
924 return sd_bus_reply_method_errno(bus, message, r, NULL);
926 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
928 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_USER, "No user '%lu' known or logged in", (unsigned long) uid);
932 return sd_bus_reply_method_errno(bus, message, r, NULL);
934 return sd_bus_reply_method_return(bus, message, NULL);
937 static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata) {
938 Manager *m = userdata;
947 r = sd_bus_message_read(message, "s", &name);
949 return sd_bus_reply_method_errno(bus, message, r, NULL);
951 seat = hashmap_get(m->seats, name);
953 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
955 r = seat_stop_sessions(seat);
957 return sd_bus_reply_method_errno(bus, message, r, NULL);
959 return sd_bus_reply_method_return(bus, message, NULL);
962 static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata) {
963 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
964 _cleanup_free_ char *cc = NULL;
965 Manager *m = userdata;
976 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
978 return sd_bus_reply_method_errno(bus, message, r, NULL);
983 return sd_bus_reply_method_errno(bus, message, errno ? errno : ENOENT, NULL);
985 r = bus_verify_polkit_async(bus,
988 "org.freedesktop.login1.set-user-linger",
991 method_set_user_linger, m);
993 return sd_bus_reply_method_errno(bus, message, r, &error);
995 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
997 mkdir_p_label("/var/lib/systemd", 0755);
999 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1001 return sd_bus_reply_method_errno(bus, message, r, NULL);
1003 cc = cescape(pw->pw_name);
1005 return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
1007 path = strappenda("/var/lib/systemd/linger/", cc);
1013 return sd_bus_reply_method_errno(bus, message, r, NULL);
1015 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1022 if (r < 0 && errno != ENOENT)
1023 return sd_bus_reply_method_errno(bus, message, errno, NULL);
1025 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1027 user_add_to_gc_queue(u);
1030 return sd_bus_reply_method_return(bus, message, NULL);
1033 static int trigger_device(Manager *m, struct udev_device *d) {
1034 struct udev_enumerate *e;
1035 struct udev_list_entry *first, *item;
1040 e = udev_enumerate_new(m->udev);
1047 if (udev_enumerate_add_match_parent(e, d) < 0) {
1053 if (udev_enumerate_scan_devices(e) < 0) {
1058 first = udev_enumerate_get_list_entry(e);
1059 udev_list_entry_foreach(item, first) {
1060 _cleanup_free_ char *t = NULL;
1063 p = udev_list_entry_get_name(item);
1065 t = strappend(p, "/uevent");
1071 write_string_file(t, "change");
1078 udev_enumerate_unref(e);
1083 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1084 _cleanup_free_ char *rule = NULL, *file = NULL;
1085 const char *id_for_seat;
1086 struct udev_device *d;
1093 d = udev_device_new_from_syspath(m->udev, sysfs);
1097 if (!udev_device_has_tag(d, "seat")) {
1102 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1108 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0) {
1113 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) {
1118 mkdir_p_label("/etc/udev/rules.d", 0755);
1120 r = write_string_file_atomic_label(file, rule);
1124 r = trigger_device(m, d);
1128 udev_device_unref(d);
1133 static int flush_devices(Manager *m) {
1134 _cleanup_closedir_ DIR *d;
1138 d = opendir("/etc/udev/rules.d");
1140 if (errno != ENOENT)
1141 log_warning("Failed to open /etc/udev/rules.d: %m");
1145 while ((de = readdir(d))) {
1147 if (!dirent_is_file(de))
1150 if (!startswith(de->d_name, "72-seat-"))
1153 if (!endswith(de->d_name, ".rules"))
1156 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1157 log_warning("Failed to unlink %s: %m", de->d_name);
1161 return trigger_device(m, NULL);
1164 static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata) {
1165 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1166 const char *sysfs, *seat;
1167 Manager *m = userdata;
1174 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1176 return sd_bus_reply_method_errno(bus, message, r, NULL);
1178 if (!path_startswith(sysfs, "/sys"))
1179 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1181 if (!seat_name_is_valid(seat))
1182 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1184 r = bus_verify_polkit_async(bus,
1185 &m->polkit_registry,
1187 "org.freedesktop.login1.attach-device",
1190 method_attach_device, m);
1192 return sd_bus_reply_method_errno(bus, message, r, &error);
1194 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1196 r = attach_device(m, seat, sysfs);
1198 return sd_bus_reply_method_errno(bus, message, r, NULL);
1200 return sd_bus_reply_method_return(bus, message, NULL);
1203 static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata) {
1204 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1205 Manager *m = userdata;
1212 r = sd_bus_message_read(message, "b", &interactive);
1214 return sd_bus_reply_method_errno(bus, message, r, NULL);
1216 r = bus_verify_polkit_async(bus,
1217 &m->polkit_registry,
1219 "org.freedesktop.login1.flush-devices",
1222 method_flush_devices, m);
1224 return sd_bus_reply_method_errno(bus, message, r, &error);
1226 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1228 r = flush_devices(m);
1230 return sd_bus_reply_method_errno(bus, message, r, &error);
1232 return sd_bus_reply_method_return(bus, message, NULL);
1235 static int have_multiple_sessions(
1244 /* Check for other users' sessions. Greeter sessions do not
1245 * count, and non-login sessions do not count either. */
1246 HASHMAP_FOREACH(session, m->sessions, i)
1247 if (session->class == SESSION_USER &&
1248 !session->closing &&
1249 session->user->uid != uid)
1255 static int bus_manager_log_shutdown(
1258 const char *unit_name) {
1265 if (w != INHIBIT_SHUTDOWN)
1268 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1269 p = "MESSAGE=System is powering down.";
1270 q = "SHUTDOWN=power-off";
1271 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1272 p = "MESSAGE=System is halting.";
1273 q = "SHUTDOWN=halt";
1274 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1275 p = "MESSAGE=System is rebooting.";
1276 q = "SHUTDOWN=reboot";
1277 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1278 p = "MESSAGE=System is rebooting with kexec.";
1279 q = "SHUTDOWN=kexec";
1281 p = "MESSAGE=System is shutting down.";
1285 return log_struct(LOG_NOTICE, MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1290 static int execute_shutdown_or_sleep(
1293 const char *unit_name,
1294 sd_bus_error *error) {
1296 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1303 assert(w < _INHIBIT_WHAT_MAX);
1306 bus_manager_log_shutdown(m, w, unit_name);
1308 r = sd_bus_call_method(
1310 "org.freedesktop.systemd1",
1311 "/org/freedesktop/systemd1",
1312 "org.freedesktop.systemd1.Manager",
1316 "ss", unit_name, "replace-irreversibly");
1320 r = sd_bus_message_read(reply, "o", &p);
1328 m->action_unit = unit_name;
1329 free(m->action_job);
1336 static int delay_shutdown_or_sleep(
1339 const char *unit_name) {
1343 assert(w < _INHIBIT_WHAT_MAX);
1346 m->action_timestamp = now(CLOCK_MONOTONIC);
1347 m->action_unit = unit_name;
1353 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1355 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1356 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1357 [INHIBIT_SLEEP] = "PrepareForSleep"
1360 int active = _active;
1364 assert(w < _INHIBIT_WHAT_MAX);
1365 assert(signal_name[w]);
1367 return sd_bus_emit_signal(m->bus,
1368 "/org/freedesktop/login1",
1369 "org.freedesktop.login1.Manager",
1375 int bus_manager_shutdown_or_sleep_now_or_later(
1377 const char *unit_name,
1379 sd_bus_error *error) {
1387 assert(w <= _INHIBIT_WHAT_MAX);
1388 assert(!m->action_job);
1390 /* Tell everybody to prepare for shutdown/sleep */
1391 send_prepare_for(m, w, true);
1394 m->inhibit_delay_max > 0 &&
1395 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0);
1398 /* Shutdown is delayed, keep in mind what we
1399 * want to do, and start a timeout */
1400 r = delay_shutdown_or_sleep(m, w, unit_name);
1402 /* Shutdown is not delayed, execute it
1404 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1409 static int method_do_shutdown_or_sleep(
1411 sd_bus_message *message,
1412 const char *unit_name,
1415 const char *action_multiple_sessions,
1416 const char *action_ignore_inhibit,
1417 const char *sleep_verb,
1418 sd_bus_message_handler_t method) {
1420 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1421 bool multiple_sessions, blocked;
1429 assert(w <= _INHIBIT_WHAT_MAX);
1431 assert(action_multiple_sessions);
1432 assert(action_ignore_inhibit);
1435 r = sd_bus_message_read(message, "b", &interactive);
1437 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1439 /* Don't allow multiple jobs being executed at the same time */
1441 return sd_bus_reply_method_errorf(m->bus, message, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1444 r = can_sleep(sleep_verb);
1446 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1449 return sd_bus_reply_method_errorf(m->bus, message, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1452 r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
1454 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1456 r = have_multiple_sessions(m, uid);
1458 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1460 multiple_sessions = r > 0;
1461 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid);
1463 if (multiple_sessions) {
1464 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
1465 action_multiple_sessions, interactive, &error, method, m);
1467 return sd_bus_reply_method_errno(m->bus, message, r, &error);
1471 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
1472 action_ignore_inhibit, interactive, &error, method, m);
1474 return sd_bus_reply_method_errno(m->bus, message, r, &error);
1477 if (!multiple_sessions && !blocked) {
1478 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
1479 action, interactive, &error, method, m);
1481 return sd_bus_reply_method_errno(m->bus, message, r, &error);
1484 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, &error);
1486 return sd_bus_reply_method_errno(m->bus, message, r, &error);
1488 return sd_bus_reply_method_return(m->bus, message, NULL);
1491 static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata) {
1492 Manager *m = userdata;
1494 return method_do_shutdown_or_sleep(
1496 SPECIAL_POWEROFF_TARGET,
1498 "org.freedesktop.login1.power-off",
1499 "org.freedesktop.login1.power-off-multiple-sessions",
1500 "org.freedesktop.login1.power-off-ignore-inhibit",
1505 static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata) {
1506 Manager *m = userdata;
1508 return method_do_shutdown_or_sleep(
1510 SPECIAL_REBOOT_TARGET,
1512 "org.freedesktop.login1.reboot",
1513 "org.freedesktop.login1.reboot-multiple-sessions",
1514 "org.freedesktop.login1.reboot-ignore-inhibit",
1519 static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata) {
1520 Manager *m = userdata;
1522 return method_do_shutdown_or_sleep(
1524 SPECIAL_SUSPEND_TARGET,
1526 "org.freedesktop.login1.suspend",
1527 "org.freedesktop.login1.suspend-multiple-sessions",
1528 "org.freedesktop.login1.suspend-ignore-inhibit",
1533 static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata) {
1534 Manager *m = userdata;
1536 return method_do_shutdown_or_sleep(
1538 SPECIAL_HIBERNATE_TARGET,
1540 "org.freedesktop.login1.hibernate",
1541 "org.freedesktop.login1.hibernate-multiple-sessions",
1542 "org.freedesktop.login1.hibernate-ignore-inhibit",
1547 static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata) {
1548 Manager *m = userdata;
1550 return method_do_shutdown_or_sleep(
1552 SPECIAL_HYBRID_SLEEP_TARGET,
1554 "org.freedesktop.login1.hibernate",
1555 "org.freedesktop.login1.hibernate-multiple-sessions",
1556 "org.freedesktop.login1.hibernate-ignore-inhibit",
1558 method_hybrid_sleep);
1561 static int method_can_shutdown_or_sleep(
1563 sd_bus_message *message,
1566 const char *action_multiple_sessions,
1567 const char *action_ignore_inhibit,
1568 const char *sleep_verb) {
1570 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1571 bool multiple_sessions, challenge, blocked;
1572 const char *result = NULL;
1579 assert(w <= _INHIBIT_WHAT_MAX);
1581 assert(action_multiple_sessions);
1582 assert(action_ignore_inhibit);
1585 r = can_sleep(sleep_verb);
1587 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1589 return sd_bus_reply_method_return(m->bus, message, "s", "na");
1592 r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
1594 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1596 r = have_multiple_sessions(m, uid);
1598 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1600 multiple_sessions = r > 0;
1601 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid);
1603 if (multiple_sessions) {
1604 r = bus_verify_polkit(m->bus, message, action_multiple_sessions, false, &challenge, &error);
1606 return sd_bus_reply_method_errno(m->bus, message, r, &error);
1611 result = "challenge";
1617 r = bus_verify_polkit(m->bus, message, action_ignore_inhibit, false, &challenge, &error);
1619 return sd_bus_reply_method_errno(m->bus, message, r, &error);
1621 if (r > 0 && !result)
1623 else if (challenge && (!result || streq(result, "yes")))
1624 result = "challenge";
1629 if (!multiple_sessions && !blocked) {
1630 /* If neither inhibit nor multiple sessions
1631 * apply then just check the normal policy */
1633 r = bus_verify_polkit(m->bus, message, action, false, &challenge, &error);
1635 return sd_bus_reply_method_errno(m->bus, message, r, &error);
1640 result = "challenge";
1645 return sd_bus_reply_method_return(m->bus, message, "s", result);
1648 static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata) {
1649 Manager *m = userdata;
1651 return method_can_shutdown_or_sleep(
1654 "org.freedesktop.login1.power-off",
1655 "org.freedesktop.login1.power-off-multiple-sessions",
1656 "org.freedesktop.login1.power-off-ignore-inhibit",
1660 static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata) {
1661 Manager *m = userdata;
1663 return method_can_shutdown_or_sleep(
1666 "org.freedesktop.login1.reboot",
1667 "org.freedesktop.login1.reboot-multiple-sessions",
1668 "org.freedesktop.login1.reboot-ignore-inhibit",
1672 static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata) {
1673 Manager *m = userdata;
1675 return method_can_shutdown_or_sleep(
1678 "org.freedesktop.login1.suspend",
1679 "org.freedesktop.login1.suspend-multiple-sessions",
1680 "org.freedesktop.login1.suspend-ignore-inhibit",
1684 static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata) {
1685 Manager *m = userdata;
1687 return method_can_shutdown_or_sleep(
1690 "org.freedesktop.login1.hibernate",
1691 "org.freedesktop.login1.hibernate-multiple-sessions",
1692 "org.freedesktop.login1.hibernate-ignore-inhibit",
1696 static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata) {
1697 Manager *m = userdata;
1699 return method_can_shutdown_or_sleep(
1702 "org.freedesktop.login1.hibernate",
1703 "org.freedesktop.login1.hibernate-multiple-sessions",
1704 "org.freedesktop.login1.hibernate-ignore-inhibit",
1708 static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata) {
1709 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1710 const char *who, *why, *what, *mode;
1711 _cleanup_free_ char *id = NULL;
1712 _cleanup_close_ int fifo_fd = -1;
1713 Manager *m = userdata;
1714 Inhibitor *i = NULL;
1725 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1727 return sd_bus_reply_method_errno(bus, message, r, NULL);
1729 w = inhibit_what_from_string(what);
1731 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
1733 mm = inhibit_mode_from_string(mode);
1735 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
1737 /* Delay is only supported for shutdown/sleep */
1738 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1739 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
1741 /* Don't allow taking delay locks while we are already
1742 * executing the operation. We shouldn't create the impression
1743 * that the lock was successful if the machine is about to go
1744 * down/suspend any moment. */
1745 if (m->action_what & w)
1746 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1748 r = bus_verify_polkit_async(bus, &m->polkit_registry, message,
1749 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1750 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1751 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1752 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1753 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1754 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1755 "org.freedesktop.login1.inhibit-handle-lid-switch",
1756 false, &error, method_inhibit, m);
1758 return sd_bus_reply_method_errno(bus, message, r, &error);
1760 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1762 r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
1764 return sd_bus_reply_method_errno(bus, message, r, NULL);
1766 r = sd_bus_get_owner_pid(m->bus, sd_bus_message_get_sender(message), &pid);
1768 return sd_bus_reply_method_errno(bus, message, r, NULL);
1774 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1775 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
1777 } while (hashmap_get(m->inhibitors, id));
1779 r = manager_add_inhibitor(m, id, &i);
1781 return sd_bus_reply_method_errno(bus, message, r, NULL);
1787 i->why = strdup(why);
1788 i->who = strdup(who);
1790 if (!i->why || !i->who) {
1791 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
1795 fifo_fd = inhibitor_create_fifo(i);
1797 r = sd_bus_reply_method_errno(bus, message, fifo_fd, NULL);
1803 return sd_bus_reply_method_return(bus, message, "h", fifo_fd);
1812 const sd_bus_vtable manager_vtable[] = {
1813 SD_BUS_VTABLE_START(0),
1815 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), 0),
1816 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), 0),
1817 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), 0),
1818 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), 0),
1819 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1820 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1821 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1822 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1823 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1824 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), 0),
1825 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), 0),
1826 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), 0),
1827 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), 0),
1828 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), 0),
1829 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), 0),
1830 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), 0),
1831 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1832 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1834 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, 0),
1835 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, 0),
1836 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, 0),
1837 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, 0),
1838 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, 0),
1839 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, 0),
1840 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, 0),
1841 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, 0),
1842 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, 0),
1843 SD_BUS_METHOD("CreateSession", "uussssussbssa(sv)", "soshsub", method_create_session, 0),
1844 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
1845 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0),
1846 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, 0),
1847 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, 0),
1848 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, 0),
1849 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, 0),
1850 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, 0),
1851 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, 0),
1852 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, 0),
1853 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, 0),
1854 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, 0),
1855 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, 0),
1856 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, 0),
1857 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, 0),
1858 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, 0),
1859 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, 0),
1860 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, 0),
1861 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, 0),
1862 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, 0),
1863 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, 0),
1864 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, 0),
1865 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, 0),
1866 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, 0),
1867 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, 0),
1868 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, 0),
1869 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, 0),
1871 SD_BUS_SIGNAL("SessionNew", "so", 0),
1872 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
1873 SD_BUS_SIGNAL("UserNew", "uo", 0),
1874 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
1875 SD_BUS_SIGNAL("SeatNew", "so", 0),
1876 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
1877 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
1878 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
1883 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata) {
1884 const char *path, *result, *unit;
1885 Manager *m = userdata;
1895 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
1897 log_error("Failed to parse JobRemoved message: %s", strerror(-r));
1901 if (m->action_job && streq(m->action_job, path)) {
1902 log_info("Operation finished.");
1904 /* Tell people that they now may take a lock again */
1905 send_prepare_for(m, m->action_what, false);
1907 free(m->action_job);
1908 m->action_job = NULL;
1909 m->action_unit = NULL;
1914 session = hashmap_get(m->session_units, unit);
1917 if (streq_ptr(path, session->scope_job)) {
1918 free(session->scope_job);
1919 session->scope_job = NULL;
1922 if (session->started) {
1923 if (streq(result, "done"))
1924 session_send_create_reply(session, NULL);
1926 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1928 sd_bus_error_setf(&error, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
1929 session_send_create_reply(session, &error);
1932 session_save(session);
1934 session_add_to_gc_queue(session);
1937 user = hashmap_get(m->user_units, unit);
1940 if (streq_ptr(path, user->service_job)) {
1941 free(user->service_job);
1942 user->service_job = NULL;
1945 if (streq_ptr(path, user->slice_job)) {
1946 free(user->slice_job);
1947 user->slice_job = NULL;
1951 user_add_to_gc_queue(user);
1957 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata) {
1958 const char *path, *unit;
1959 Manager *m = userdata;
1968 r = sd_bus_message_read(message, "so", &unit, &path);
1970 log_error("Failed to parse UnitRemoved message: %s", strerror(-r));
1974 session = hashmap_get(m->session_units, unit);
1976 session_add_to_gc_queue(session);
1978 user = hashmap_get(m->user_units, unit);
1980 user_add_to_gc_queue(user);
1985 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
1986 _cleanup_free_ char *unit = NULL;
1987 Manager *m = userdata;
1996 path = sd_bus_message_get_path(message);
2000 unit_name_from_dbus_path(path, &unit);
2004 session = hashmap_get(m->session_units, unit);
2006 session_add_to_gc_queue(session);
2008 user = hashmap_get(m->user_units, unit);
2010 user_add_to_gc_queue(user);
2015 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata) {
2016 Manager *m = userdata;
2023 r = sd_bus_message_read(message, "b", &b);
2025 log_error("Failed to parse Reloading message: %s", strerror(-r));
2032 /* systemd finished reloading, let's recheck all our sessions */
2033 log_debug("System manager has been reloaded, rechecking sessions...");
2035 HASHMAP_FOREACH(session, m->sessions, i)
2036 session_add_to_gc_queue(session);
2041 int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
2042 const char *name, *old, *new;
2043 Manager *m = userdata;
2051 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2053 log_error("Failed to parse NameOwnerChanged message: %s", strerror(-r));
2057 if (isempty(old) || !isempty(new))
2060 key = set_remove(m->busnames, (char*) old);
2064 /* Drop all controllers owned by this name */
2068 HASHMAP_FOREACH(session, m->sessions, i)
2069 if (session_is_controller(session, old))
2070 session_drop_controller(session);
2075 int manager_send_changed(Manager *manager, const char *property, ...) {
2080 l = strv_from_stdarg_alloca(property);
2082 return sd_bus_emit_properties_changed_strv(
2084 "/org/freedesktop/login1",
2085 "org.freedesktop.login1.Manager",
2089 int manager_dispatch_delayed(Manager *manager) {
2090 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2095 if (manager->action_what == 0 || manager->action_job)
2098 /* Continue delay? */
2099 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0)) {
2101 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2104 log_info("Delay lock is active but inhibitor timeout is reached.");
2107 /* Actually do the operation */
2108 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
2110 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
2112 manager->action_unit = NULL;
2113 manager->action_what = 0;
2120 int manager_start_scope(
2125 const char *description,
2127 const char *kill_mode,
2128 sd_bus_error *error,
2131 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2138 r = sd_bus_message_new_method_call(
2140 "org.freedesktop.systemd1",
2141 "/org/freedesktop/systemd1",
2142 "org.freedesktop.systemd1.Manager",
2143 "StartTransientUnit",
2148 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2152 r = sd_bus_message_open_container(m, 'a', "(sv)");
2156 if (!isempty(slice)) {
2157 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2162 if (!isempty(description)) {
2163 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2168 if (!isempty(description)) {
2169 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2174 if (!isempty(kill_mode)) {
2175 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", kill_mode);
2180 /* cgroup empty notification is not available in containers
2181 * currently. To make this less problematic, let's shorten the
2182 * stop timeout for sessions, so that we don't wait
2185 r = sd_bus_message_append(m, "(sv)", "TimeoutStopUSec", "t", 500 * USEC_PER_MSEC);
2189 /* Make sure that the session shells are terminated with
2190 * SIGHUP since bash and friends tend to ignore SIGTERM */
2191 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2195 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2199 r = sd_bus_message_close_container(m);
2203 r = sd_bus_send_with_reply_and_block(manager->bus, m, 0, error, &reply);
2211 r = sd_bus_message_read(reply, "o", &j);
2225 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2226 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2232 r = sd_bus_call_method(
2234 "org.freedesktop.systemd1",
2235 "/org/freedesktop/systemd1",
2236 "org.freedesktop.systemd1.Manager",
2240 "ss", unit, "fail");
2248 r = sd_bus_message_read(reply, "o", &j);
2262 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2263 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2269 r = sd_bus_call_method(
2271 "org.freedesktop.systemd1",
2272 "/org/freedesktop/systemd1",
2273 "org.freedesktop.systemd1.Manager",
2277 "ss", unit, "fail");
2279 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2280 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2285 sd_bus_error_free(error);
2296 r = sd_bus_message_read(reply, "o", &j);
2310 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2314 return sd_bus_call_method(
2316 "org.freedesktop.systemd1",
2317 "/org/freedesktop/systemd1",
2318 "org.freedesktop.systemd1.Manager",
2322 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2325 int manager_unit_is_active(Manager *manager, const char *unit) {
2326 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2327 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2328 _cleanup_free_ char *path = NULL;
2335 path = unit_dbus_path_from_name(unit);
2339 r = sd_bus_get_property(
2341 "org.freedesktop.systemd1",
2343 "org.freedesktop.systemd1.Unit",
2349 /* systemd might have droppped off momentarily, let's
2350 * not make this an error */
2351 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2352 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2355 /* If the unit is already unloaded then it's not
2357 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2358 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2364 r = sd_bus_message_read(reply, "s", &state);
2368 return !streq(state, "inactive") && !streq(state, "failed");
2371 int manager_job_is_active(Manager *manager, const char *path) {
2372 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2373 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2379 r = sd_bus_get_property(
2381 "org.freedesktop.systemd1",
2383 "org.freedesktop.systemd1.Job",
2389 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2390 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2393 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2399 /* We don't actually care about the state really. The fact
2400 * that we could read the job state is enough for us */