X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogin%2Flogind-dbus.c;h=0a30dfd160b6b7abab83411368ceed74c4d1189e;hp=d88636f7471a4b1afa2da1162f3a574d5222fddb;hb=ad0ff86c7c90c3d652edb7c81ebd3f07f70a9a07;hpb=2bd94bfa67be6bc52fd525396fd87b4a6f323bed diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index d88636f74..0a30dfd16 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -20,33 +18,40 @@ ***/ #include +#include #include #include -#include #include "sd-messages.h" -#include "strv.h" -#include "mkdir.h" -#include "path-util.h" -// #include "special.h" -#include "sleep-config.h" -#include "fileio-label.h" -#include "unit-name.h" -#include "audit.h" -#include "bus-util.h" -#include "bus-error.h" + +#include "alloc-util.h" +#include "audit-util.h" #include "bus-common-errors.h" -#include "udev-util.h" -#include "selinux-util.h" -#include "efivars.h" -#include "logind.h" +#include "bus-error.h" +#include "bus-util.h" +#include "dirent-util.h" +//#include "efivars.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio-label.h" #include "formats-util.h" +#include "fs-util.h" +#include "logind.h" +#include "mkdir.h" +#include "path-util.h" #include "process-util.h" +#include "selinux-util.h" +//#include "sleep-config.h" +//#include "special.h" +#include "strv.h" #include "terminal-util.h" -#include "utmp-wtmp.h" +#include "udev-util.h" +#include "unit-name.h" +#include "user-util.h" +//#include "utmp-wtmp.h" int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; Session *session; int r; @@ -81,7 +86,7 @@ int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, assert(ret); if (uid == UID_INVALID) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; /* Note that we get the owner UID of the session, not the actual client UID here! */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); @@ -117,7 +122,6 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char return r; seat = session->seat; - if (!seat) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat."); } else { @@ -261,6 +265,42 @@ static int property_get_docked( return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m)); } +static int property_get_current_sessions( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions)); +} + +static int property_get_current_inhibitors( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors)); +} + static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; @@ -301,8 +341,10 @@ static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd r = sd_bus_message_read(message, "u", &pid); if (r < 0) return r; + if (pid < 0) + return -EINVAL; - if (pid <= 0) { + if (pid == 0) { r = manager_get_session_from_creds(m, message, NULL, error, &session); if (r < 0) return r; @@ -362,8 +404,10 @@ static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bu r = sd_bus_message_read(message, "u", &pid); if (r < 0) return r; + if (pid < 0) + return -EINVAL; - if (pid <= 0) { + if (pid == 0) { r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user); if (r < 0) return r; @@ -408,7 +452,7 @@ static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error } static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Session *session; Iterator i; @@ -450,7 +494,7 @@ static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_ } static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; User *user; Iterator i; @@ -490,7 +534,7 @@ static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_err } static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Seat *seat; Iterator i; @@ -527,7 +571,7 @@ static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_err } static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Inhibitor *inhibitor; Iterator i; @@ -566,12 +610,14 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop; - uint32_t uid, leader, audit_id = 0; + uint32_t audit_id = 0; _cleanup_free_ char *id = NULL; Session *session = NULL; Manager *m = userdata; User *user = NULL; Seat *seat = NULL; + pid_t leader; + uid_t uid; int remote; uint32_t vtnr = 0; SessionType t; @@ -581,11 +627,16 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus assert(message); assert(m); + assert_cc(sizeof(pid_t) == sizeof(uint32_t)); + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); + r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host); if (r < 0) return r; - if (leader == 1) + if (!uid_is_valid(uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID"); + if (leader < 0 || leader == 1) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID"); if (isempty(type)) @@ -677,8 +728,8 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus c = SESSION_USER; } - if (leader <= 0) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + if (leader == 0) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) @@ -710,6 +761,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus m->seat0->positions[vtnr]->class != SESSION_GREETER) return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session"); + if (hashmap_size(m->sessions) >= m->sessions_max) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max); + audit_session_from_pid(leader, &audit_id); if (audit_id > 0) { /* Keep our session IDs and the audit session IDs in sync */ @@ -1068,11 +1122,11 @@ static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *cc = NULL; Manager *m = userdata; - int b, r; + int r, b, interactive; struct passwd *pw; const char *path; uint32_t uid; - int interactive; + bool self = false; assert(message); assert(m); @@ -1082,7 +1136,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu return r; if (uid == UID_INVALID) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; /* Note that we get the owner UID of the session, not the actual client UID here! */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); @@ -1092,17 +1146,21 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu r = sd_bus_creds_get_owner_uid(creds, &uid); if (r < 0) return r; - } + + self = true; + + } else if (!uid_is_valid(uid)) + return -EINVAL; errno = 0; pw = getpwuid(uid); if (!pw) - return errno ? -errno : -ENOENT; + return errno > 0 ? -errno : -ENOENT; r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, - "org.freedesktop.login1.set-user-linger", + self ? "org.freedesktop.login1.set-self-linger" : "org.freedesktop.login1.set-user-linger", NULL, interactive, UID_INVALID, @@ -1215,7 +1273,6 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) { return -ENOMEM; mkdir_p_label("/etc/udev/rules.d", 0755); - mac_selinux_init("/etc"); r = write_string_file_atomic_label(file, rule); if (r < 0) return r; @@ -1347,39 +1404,69 @@ static int have_multiple_sessions( static int bus_manager_log_shutdown( Manager *m, InhibitWhat w, - HandleAction action) { +#if 0 /// elogind does not support systemd units + const char *unit_name) { const char *p, *q; assert(m); + assert(unit_name); if (w != INHIBIT_SHUTDOWN) return 0; - switch (action) { - case HANDLE_POWEROFF: - p = "MESSAGE=System is powering down."; + if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) { + p = "MESSAGE=System is powering down"; q = "SHUTDOWN=power-off"; - break; - case HANDLE_HALT: - p = "MESSAGE=System is halting."; + } else if (streq(unit_name, SPECIAL_HALT_TARGET)) { + p = "MESSAGE=System is halting"; q = "SHUTDOWN=halt"; - break; - case HANDLE_REBOOT: - p = "MESSAGE=System is rebooting."; + } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) { + p = "MESSAGE=System is rebooting"; q = "SHUTDOWN=reboot"; - break; - case HANDLE_KEXEC: - p = "MESSAGE=System is rebooting with kexec."; + } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) { + p = "MESSAGE=System is rebooting with kexec"; q = "SHUTDOWN=kexec"; - break; - default: - p = "MESSAGE=System is shutting down."; + } else { + p = "MESSAGE=System is shutting down"; q = NULL; } - - if (!isempty(m->wall_message)) - p = strjoina(p, " (", m->wall_message, ")"); +#else + HandleAction action) { + + const char *p, *q; + + assert(m); + + if (w != INHIBIT_SHUTDOWN) + return 0; + + switch (action) { + case HANDLE_POWEROFF: + p = "MESSAGE=System is powering down."; + q = "SHUTDOWN=power-off"; + break; + case HANDLE_HALT: + p = "MESSAGE=System is halting."; + q = "SHUTDOWN=halt"; + break; + case HANDLE_REBOOT: + p = "MESSAGE=System is rebooting."; + q = "SHUTDOWN=reboot"; + break; + case HANDLE_KEXEC: + p = "MESSAGE=System is rebooting with kexec."; + q = "SHUTDOWN=kexec"; + break; + default: + p = "MESSAGE=System is shutting down."; + q = NULL; + } +#endif // 0 + if (isempty(m->wall_message)) + p = strjoina(p, "."); + else + p = strjoina(p, " (", m->wall_message, ")."); return log_struct(LOG_NOTICE, LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), @@ -1433,26 +1520,18 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) { return r; } -static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { - - static const char * const signal_name[_INHIBIT_WHAT_MAX] = { - [INHIBIT_SHUTDOWN] = "PrepareForShutdown", - [INHIBIT_SLEEP] = "PrepareForSleep" - }; - - int active = _active; - - assert(m); - assert(w >= 0); - assert(w < _INHIBIT_WHAT_MAX); - assert(signal_name[w]); +static void reset_scheduled_shutdown(Manager *m) { + m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); + m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source); + m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source); + m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type); + m->scheduled_shutdown_timeout = 0; + m->shutdown_dry_run = false; - return sd_bus_emit_signal(m->bus, - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - signal_name[w], - "b", - active); + if (m->unlink_nologin) { + (void) unlink("/run/nologin"); + m->unlink_nologin = false; + } } static int execute_shutdown_or_sleep( @@ -1461,11 +1540,10 @@ static int execute_shutdown_or_sleep( HandleAction action, sd_bus_error *error) { -/// elogind does not need these, we do it ourselves -#if 0 - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; +#if 0 /// elogind does not need these, we do it ourselves + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + char *c = NULL; const char *p; - char *c; #endif // 0 int r; @@ -1475,8 +1553,11 @@ static int execute_shutdown_or_sleep( bus_manager_log_shutdown(m, w, action); -/// elogind does it directly without depending on systemd running the system -#if 0 +#if 0 /// elogind does it directly without depending on systemd running the system + if (m->shutdown_dry_run) { + log_info("Running in dry run, suppressing action."); + reset_scheduled_shutdown(m); + } else { r = sd_bus_call_method( m->bus, "org.freedesktop.systemd1", @@ -1485,15 +1566,18 @@ static int execute_shutdown_or_sleep( "StartUnit", error, &reply, - "ss", NULL, "replace-irreversibly"); + "ss", unit_name, "replace-irreversibly"); #else r = shutdown_or_sleep(m, action); + + /* no more pending actions, whether this failed or not */ + m->pending_action = HANDLE_IGNORE; + m->action_what = 0; #endif // 0 if (r < 0) return r; -/// elogind neither needs a dbus reply, nor supports systemd action jobs -#if 0 +#if 0 /// elogind neither needs a dbus reply, nor supports systemd action jobs r = sd_bus_message_read(reply, "o", &p); if (r < 0) return r; @@ -1501,6 +1585,7 @@ static int execute_shutdown_or_sleep( c = strdup(p); if (!c) return -ENOMEM; + } m->action_unit = unit_name; free(m->action_job); @@ -1508,12 +1593,6 @@ static int execute_shutdown_or_sleep( m->action_what = w; #endif // 0 - if (w == INHIBIT_SLEEP) - /* And we're back. */ - send_prepare_for(m, w, false); - - m->action_what = 0; - /* Make sure the lid switch is ignored for a while */ manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec); @@ -1522,7 +1601,7 @@ static int execute_shutdown_or_sleep( int manager_dispatch_delayed(Manager *manager, bool timeout) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Inhibitor *offending = NULL; int r; @@ -1608,6 +1687,28 @@ static int delay_shutdown_or_sleep( return 0; } +static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { + + static const char * const signal_name[_INHIBIT_WHAT_MAX] = { + [INHIBIT_SHUTDOWN] = "PrepareForShutdown", + [INHIBIT_SLEEP] = "PrepareForSleep" + }; + + int active = _active; + + assert(m); + assert(w >= 0); + assert(w < _INHIBIT_WHAT_MAX); + assert(signal_name[w]); + + return sd_bus_emit_signal(m->bus, + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + signal_name[w], + "b", + active); +} + int bus_manager_shutdown_or_sleep_now_or_later( Manager *m, HandleAction action, @@ -1650,7 +1751,7 @@ static int verify_shutdown_creds( const char *action_ignore_inhibit, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; bool multiple_sessions, blocked; uid_t uid; int r; @@ -1729,7 +1830,7 @@ static int method_do_shutdown_or_sleep( return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress"); if (sleep_verb) { - r = can_sleep(sleep_verb); + r = can_sleep(m, sleep_verb); if (r < 0) return r; @@ -1801,7 +1902,7 @@ static int nologin_timeout_handler( log_info("Creating /run/nologin, blocking further logins..."); - r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); + r = write_string_file_atomic_label("/run/nologin", "System is going down."); if (r < 0) log_error_errno(r, "Failed to create /run/nologin: %m"); else @@ -1870,7 +1971,7 @@ static int manager_scheduled_shutdown_handler( uint64_t usec, void *userdata) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Manager *m = userdata; HandleAction action; int r; @@ -1896,7 +1997,7 @@ static int manager_scheduled_shutdown_handler( static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *action_multiple_sessions = NULL; const char *action_ignore_inhibit = NULL; const char *action = NULL; @@ -1911,6 +2012,11 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_ if (r < 0) return r; + if (startswith(type, "dry-")) { + type += 4; + m->shutdown_dry_run = true; + } + if (streq(type, "reboot")) { action = "org.freedesktop.login1.reboot"; action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions"; @@ -1920,9 +2026,9 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_ action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions"; action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit"; } else if (streq(type, "poweroff")) { - action = "org.freedesktop.login1.poweroff"; - action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions"; - action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit"; + action = "org.freedesktop.login1.power-off"; + action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions"; + action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit"; } else return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type"); @@ -1971,7 +2077,7 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds); if (r >= 0) { - const char *tty; + const char *tty = NULL; (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid); (void) sd_bus_creds_get_tty(creds, &tty); @@ -1983,9 +2089,11 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_ } } +#if 0 /// elogind does not support utmp-wtmp r = manager_setup_wall_message_timer(m); if (r < 0) return r; +#endif // 0 if (!isempty(type)) { r = update_schedule_file(m); @@ -2005,20 +2113,11 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd assert(message); cancelled = m->scheduled_shutdown_type != NULL; + reset_scheduled_shutdown(m); - m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); - m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source); - m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source); - m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type); - m->scheduled_shutdown_timeout = 0; - - if (m->unlink_nologin) { - (void) unlink("/run/nologin"); - m->unlink_nologin = false; - } - +#if 0 /// elogind does not support utmp-wtmp if (cancelled) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *tty = NULL; uid_t uid = 0; int r; @@ -2030,8 +2129,9 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd } utmp_wall("The system shutdown has been cancelled", - lookup_uid(uid), tty, logind_wall_tty_filter, m); + uid_to_name(uid), tty, logind_wall_tty_filter, m); } +#endif // 0 return sd_bus_reply_method_return(message, "b", cancelled); } @@ -2074,7 +2174,7 @@ static int method_can_shutdown_or_sleep( const char *sleep_verb, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; bool multiple_sessions, challenge, blocked; const char *result = NULL; uid_t uid; @@ -2089,7 +2189,7 @@ static int method_can_shutdown_or_sleep( assert(action_ignore_inhibit); if (sleep_verb) { - r = can_sleep(sleep_verb); + r = can_sleep(m, sleep_verb); if (r < 0) return r; if (r == 0) @@ -2229,6 +2329,7 @@ static int property_get_reboot_to_firmware_setup( sd_bus_message *reply, void *userdata, sd_bus_error *error) { +#if 0 /// elogind does not support EFI int r; assert(bus); @@ -2240,6 +2341,9 @@ static int property_get_reboot_to_firmware_setup( return r; return sd_bus_message_append(reply, "b", r > 0); +#else + return sd_bus_message_append(reply, "b", -EOPNOTSUPP); +#endif // 0 } static int method_set_reboot_to_firmware_setup( @@ -2270,9 +2374,11 @@ static int method_set_reboot_to_firmware_setup( if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ +#if 0 /// elogind does not support EFI r = efi_set_reboot_to_firmware(b); if (r < 0) return r; +#endif // 0 return sd_bus_reply_method_return(message, NULL); } @@ -2282,6 +2388,7 @@ static int method_can_reboot_to_firmware_setup( void *userdata, sd_bus_error *error) { +#if 0 /// elogind does not support EFI int r; bool challenge; const char *result; @@ -2314,6 +2421,9 @@ static int method_can_reboot_to_firmware_setup( result = "no"; return sd_bus_reply_method_return(message, "s", result); +#else + return sd_bus_reply_method_return(message, "s", "na"); +#endif // 0 } static int method_set_wall_message( @@ -2360,7 +2470,7 @@ static int method_set_wall_message( } static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *who, *why, *what, *mode; _cleanup_free_ char *id = NULL; _cleanup_close_ int fifo_fd = -1; @@ -2430,6 +2540,9 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error if (r < 0) return r; + if (hashmap_size(m->inhibitors) >= m->inhibitors_max) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max); + do { id = mfree(id); @@ -2500,6 +2613,13 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0), SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0), + SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0), + SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0), + SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), @@ -2555,8 +2675,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_END }; -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind static int session_jobs_reply(Session *s, const char *unit, const char *result) { int r = 0; @@ -2569,7 +2688,7 @@ static int session_jobs_reply(Session *s, const char *unit, const char *result) if (streq(result, "done")) r = session_send_create_reply(s, NULL); else { - _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; 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); @@ -2741,19 +2860,110 @@ int manager_send_changed(Manager *manager, const char *property, ...) { l); } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind +static int strdup_job(sd_bus_message *reply, char **job) { + const char *j; + char *copy; + int r; + + r = sd_bus_message_read(reply, "o", &j); + if (r < 0) + return r; + + copy = strdup(j); + if (!copy) + return -ENOMEM; + + *job = copy; + return 1; +} + +int manager_start_slice( + Manager *manager, + const char *slice, + const char *description, + const char *after, + const char *after2, + uint64_t tasks_max, + sd_bus_error *error, + char **job) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + int r; + + assert(manager); + assert(slice); + + r = sd_bus_message_new_method_call( + manager->bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "ss", strempty(slice), "fail"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return r; + + if (!isempty(description)) { + r = sd_bus_message_append(m, "(sv)", "Description", "s", description); + if (r < 0) + return r; + } + + if (!isempty(after)) { + r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after); + if (r < 0) + return r; + } + + if (!isempty(after2)) { + r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2); + if (r < 0) + return r; + } + + r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return r; + + r = sd_bus_call(manager->bus, m, 0, error, &reply); + if (r < 0) + return r; + + if (job) + return strdup_job(reply, job); + return 1; +} + int manager_start_scope( Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, - const char *after, const char *after2, + const char *after, + const char *after2, + uint64_t tasks_max, sd_bus_error *error, char **job) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; int r; assert(manager); @@ -2817,6 +3027,10 @@ int manager_start_scope( if (r < 0) return r; + r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max); + if (r < 0) + return r; + r = sd_bus_message_close_container(m); if (r < 0) return r; @@ -2829,26 +3043,13 @@ int manager_start_scope( if (r < 0) return r; - if (job) { - const char *j; - char *copy; - - r = sd_bus_message_read(reply, "o", &j); - if (r < 0) - return r; - - copy = strdup(j); - if (!copy) - return -ENOMEM; - - *job = copy; - } - + if (job) + return strdup_job(reply, job); return 1; } int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); @@ -2866,26 +3067,13 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, if (r < 0) return r; - if (job) { - const char *j; - char *copy; - - r = sd_bus_message_read(reply, "o", &j); - if (r < 0) - return r; - - copy = strdup(j); - if (!copy) - return -ENOMEM; - - *job = copy; - } - + if (job) + return strdup_job(reply, job); return 1; } int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); @@ -2914,21 +3102,8 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c return r; } - if (job) { - const char *j; - char *copy; - - r = sd_bus_message_read(reply, "o", &j); - if (r < 0) - return r; - - copy = strdup(j); - if (!copy) - return -ENOMEM; - - *job = copy; - } - + if (job) + return strdup_job(reply, job); return 1; } @@ -2982,8 +3157,8 @@ int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo } int manager_unit_is_active(Manager *manager, const char *unit) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; const char *state; int r; @@ -3028,8 +3203,8 @@ int manager_unit_is_active(Manager *manager, const char *unit) { } int manager_job_is_active(Manager *manager, const char *path) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); @@ -3060,4 +3235,4 @@ int manager_job_is_active(Manager *manager, const char *path) { return true; } -#endif // +#endif // 0