logind-dbus.c revision 3d1c455f9a898e7427b642800644ae7142dc7557
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_bus_creds_get_session(creds, &name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering session = hashmap_get(m->sessions, name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* Note that we get the owner UID of the session, not the actual client UID here! */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_bus_creds_get_owner_uid(creds, &uid);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering user = hashmap_get(m->users, UID_TO_PTR(uid));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = manager_get_session_from_creds(m, message, NULL, error, &session);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering if (streq(property, "PreparingForShutdown"))
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering b = !!(m->action_what & INHIBIT_SHUTDOWN);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_message_append(reply, "b", b);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int property_get_scheduled_shutdown(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_message_open_container(reply, 'r', "st");
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering return sd_bus_message_close_container(reply);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmekstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmekstatic int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek r = sd_bus_message_read(message, "s", &name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert_cc(sizeof(pid_t) == sizeof(uint32_t));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_bus_message_read(message, "u", &pid);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = manager_get_session_from_creds(m, message, NULL, error, &session);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = manager_get_session_by_pid(m, pid, &session);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return sd_bus_reply_method_return(message, "o", p);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poetteringstatic int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering r = sd_bus_message_read(message, "u", &uid);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = manager_get_user_from_creds(m, message, uid, error, &user);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poetteringstatic int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek assert_cc(sizeof(pid_t) == sizeof(uint32_t));
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read(message, "u", &pid);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = manager_get_user_by_pid(m, pid, &user);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering 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);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poetteringstatic int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = sd_bus_message_read(message, "s", &name);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = manager_get_seat_from_creds(m, message, name, error, &seat);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poetteringstatic int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = sd_bus_message_new_method_return(message, &reply);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = sd_bus_message_open_container(reply, 'a', "(susso)");
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek HASHMAP_FOREACH(session, m->sessions, i) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = sd_bus_message_append(reply, "(susso)",
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek session->seat ? session->seat->id : "",
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = sd_bus_message_close_container(reply);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poetteringstatic int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(uso)");
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_bus_message_append(reply, "(uso)",
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_bus_message_close_container(reply);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return sd_bus_send(NULL, reply, NULL);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmekstatic int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(so)");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = sd_bus_message_append(reply, "(so)", seat->id, p);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = sd_bus_message_close_container(reply);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringstatic int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek r = sd_bus_message_append(reply, "(ssssuu)",
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek strempty(inhibit_what_to_string(inhibitor->what)),
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek strempty(inhibit_mode_to_string(inhibitor->mode)),
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = sd_bus_message_close_container(reply);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return sd_bus_send(NULL, reply, NULL);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmekstatic int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek uint32_t uid, leader, audit_id = 0;
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering 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);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
if (!vtnr)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
if (!seat)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
if (vtnr != 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
if (seat) {
if (vtnr != 0)
if (t == _SESSION_TYPE_INVALID) {
t = SESSION_X11;
t = SESSION_TTY;
t = SESSION_UNSPECIFIED;
if (c == _SESSION_CLASS_INVALID) {
if (t == SESSION_UNSPECIFIED)
c = SESSION_BACKGROUND;
c = SESSION_USER;
if (leader <= 0) {
if (c != SESSION_GREETER &&
vtnr > 0 &&
if (audit_id > 0) {
return -ENOMEM;
audit_id = 0;
if (!id) {
return -ENOMEM;
goto fail;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
r = -ENOMEM;
goto fail;
if (seat) {
goto fail;
goto fail;
fail:
if (session)
if (user)
const char *name;
assert(m);
const char *name;
assert(m);
static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
assert(m);
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
const char *name;
assert(m);
assert(m);
&m->polkit_registry,
error);
const char *name;
assert(m);
assert(m);
const char *name;
assert(m);
assert(m);
const char *name;
assert(m);
const char *path;
int interactive;
assert(m);
errno = 0;
if (!pw)
"org.freedesktop.login1.set-user-linger",
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
if (!cc)
return -ENOMEM;
User *u;
user_start(u);
User *u;
return -errno;
assert(m);
return -ENOMEM;
r = udev_enumerate_add_match_parent(e, d);
r = udev_enumerate_scan_devices(e);
return -ENOMEM;
const char *id_for_seat;
assert(m);
return -ENODEV;
return -ENODEV;
if (!id_for_seat)
return -ENODEV;
return -ENOMEM;
if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
return -ENOMEM;
return trigger_device(m, d);
assert(m);
int interactive, r;
assert(m);
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
int interactive, r;
assert(m);
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = flush_devices(m);
static int have_multiple_sessions(
Manager *m,
Iterator i;
assert(m);
static int bus_manager_log_shutdown(
Manager *m,
InhibitWhat w,
const char *unit_name) {
assert(m);
if (w != INHIBIT_SHUTDOWN)
q = NULL;
NULL);
assert(e);
assert(m);
assert(m);
if (m->lid_switch_ignore_event_source) {
usec_t u;
if (until <= u)
r = sd_event_add_time(
m->event,
until, 0,
static int execute_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name,
assert(m);
assert(w >= 0);
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
c = strdup(p);
return -ENOMEM;
m->action_job = c;
m->action_what = w;
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
if (!timeout)
log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
static int manager_inhibit_timeout_handler(
sd_event_source *s,
void *userdata) {
static int delay_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name) {
assert(m);
assert(w >= 0);
if (m->inhibit_timeout_source) {
m->action_what = w;
assert(m);
assert(w >= 0);
"/org/freedesktop/login1",
signal_name[w],
active);
Manager *m,
const char *unit_name,
InhibitWhat w,
bool delayed;
assert(m);
assert(w >= 0);
send_prepare_for(m, w, true);
delayed =
m->inhibit_delay_max > 0 &&
if (delayed)
static int verify_shutdown_creds(
Manager *m,
InhibitWhat w,
bool interactive,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
assert(m);
assert(w >= 0);
multiple_sessions = r > 0;
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
static int method_do_shutdown_or_sleep(
Manager *m,
const char *unit_name,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
int interactive, r;
assert(m);
assert(w >= 0);
if (m->action_what)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
if (sleep_verb) {
return method_do_shutdown_or_sleep(
m, message,
NULL,
error);
return method_do_shutdown_or_sleep(
m, message,
NULL,
error);
return method_do_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
error);
static int nologin_timeout_handler(
sd_event_source *s,
void *userdata) {
r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
m->unlink_nologin = true;
assert(m);
return log_oom();
fprintf(f,
r = fflush_and_check(f);
goto fail;
r = -errno;
goto fail;
fail:
static int manager_scheduled_shutdown_handler(
sd_event_source *s,
void *userdata) {
const char *target;
assert(m);
char *type;
assert(m);
if (m->scheduled_shutdown_timeout_source) {
return log_oom();
if (m->nologin_timeout_source) {
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
const char *tty;
return log_oom();
r = manager_setup_wall_message_timer(m);
r = update_schedule_file(m);
static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
bool cancelled;
assert(m);
m->scheduled_shutdown_timeout = 0;
if (m->unlink_nologin) {
m->unlink_nologin = false;
if (cancelled) {
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
return method_do_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
return method_do_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
static int method_can_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
assert(m);
assert(w >= 0);
if (sleep_verb) {
multiple_sessions = r > 0;
if (multiple_sessions) {
r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
else if (challenge)
if (blocked) {
if (r > 0 && !result)
else if (challenge)
return method_can_shutdown_or_sleep(
m, message,
NULL,
error);
return method_can_shutdown_or_sleep(
m, message,
NULL,
error);
return method_can_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
error);
return method_can_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
return method_can_shutdown_or_sleep(
m, message,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
error);
static int property_get_reboot_to_firmware_setup(
const char *path,
const char *interface,
const char *property,
void *userdata,
r = efi_get_reboot_to_firmware();
if (r < 0 && r != -EOPNOTSUPP)
static int method_set_reboot_to_firmware_setup(
void *userdata,
assert(m);
"org.freedesktop.login1.set-reboot-to-firmware-setup",
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = efi_set_reboot_to_firmware(b);
static int method_can_reboot_to_firmware_setup(
void *userdata,
bool challenge;
const char *result;
assert(m);
if (r == -EOPNOTSUPP)
"org.freedesktop.login1.set-reboot-to-firmware-setup",
error);
else if (challenge)
static int method_set_wall_message(
void *userdata,
char *wall_message;
int enable_wall_messages;
assert(m);
"org.freedesktop.login1.set-wall-message",
&m->polkit_registry,
error);
return log_oom();
InhibitWhat w;
assert(m);
if (mm < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
if (m->action_what & w)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
&m->polkit_registry,
error);
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
return -ENOMEM;
i->what = w;
r = -ENOMEM;
goto fail;
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
inhibitor_start(i);
fail:
inhibitor_free(i);
SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
assert(s);
if (!s->started)
sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
r = session_send_create_reply(s, &e);
assert(m);
m->action_what = 0;
if (session) {
if (user) {
assert(m);
if (session)
if (user)
const char *path;
assert(m);
if (!path)
log_oom();
if (session)
if (user)
Iterator i;
assert(m);
"/org/freedesktop/login1",
int manager_start_scope(
const char *scope,
const char *slice,
const char *description,
char **job) {
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
r = sd_bus_message_close_container(m);
if (job) {
char *copy;
if (!copy)
return -ENOMEM;
r = sd_bus_call_method(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
if (job) {
char *copy;
if (!copy)
return -ENOMEM;
r = sd_bus_call_method(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
if (job)
if (job) {
char *copy;
if (!copy)
return -ENOMEM;
if (!path)
return -ENOMEM;
r = sd_bus_call_method(
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Scope",
NULL,
NULL);
int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
return sd_bus_call_method(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
NULL,
const char *state;
if (!path)
return -ENOMEM;
r = sd_bus_get_property(
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Unit",
&error,
&reply,
return -EINVAL;
r = sd_bus_get_property(
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Job",
&error,
&reply,