diff options
Diffstat (limited to 'src/systemctl/systemctl.c')
-rw-r--r-- | src/systemctl/systemctl.c | 744 |
1 files changed, 396 insertions, 348 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 21cb898b9a..b3d90d2c33 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -22,24 +22,18 @@ #include <sys/reboot.h> #include <linux/reboot.h> -#include <sys/syscall.h> #include <stdio.h> #include <getopt.h> #include <locale.h> #include <stdbool.h> #include <string.h> #include <errno.h> -#include <sys/ioctl.h> -#include <termios.h> #include <unistd.h> #include <fcntl.h> #include <sys/socket.h> -#include <sys/stat.h> #include <stddef.h> -#include <sys/prctl.h> #include "sd-daemon.h" -#include "sd-shutdown.h" #include "sd-login.h" #include "sd-bus.h" #include "log.h" @@ -55,7 +49,6 @@ #include "cgroup-util.h" #include "list.h" #include "path-lookup.h" -#include "conf-parser.h" #include "exit-status.h" #include "build.h" #include "unit-name.h" @@ -74,6 +67,12 @@ #include "bus-common-errors.h" #include "mkdir.h" #include "dropin.h" +#include "efivars.h" +#include "formats-util.h" +#include "process-util.h" +#include "terminal-util.h" +#include "hostname-util.h" +#include "signal-util.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -138,6 +137,8 @@ static char *arg_host = NULL; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_plain = false; +static bool arg_firmware_setup = false; +static bool arg_now = false; static bool original_stdout_is_tty; @@ -252,7 +253,7 @@ static void warn_wall(enum action a) { } if (*p) { - utmp_wall(p, NULL, NULL); + utmp_wall(p, NULL, NULL, NULL, NULL); return; } } @@ -260,7 +261,7 @@ static void warn_wall(enum action a) { if (!table[a]) return; - utmp_wall(table[a], NULL, NULL); + utmp_wall(table[a], NULL, NULL, NULL, NULL); } static bool avoid_bus(void) { @@ -1327,7 +1328,6 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) { static int list_unit_files(sd_bus *bus, char **args) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ UnitFileList *units = NULL; UnitFileList *unit; size_t size = 0; @@ -1374,6 +1374,8 @@ static int list_unit_files(sd_bus *bus, char **args) { assert(c <= n_units); hashmap_free(h); } else { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -1637,13 +1639,15 @@ static int list_dependencies(sd_bus *bus, char **args) { _cleanup_strv_free_ char **units = NULL; _cleanup_free_ char *unit = NULL; const char *u; + int r; assert(bus); if (args[1]) { - unit = unit_name_mangle(args[1], MANGLE_NOGLOB); - if (!unit) - return log_oom(); + r = unit_name_mangle(args[1], UNIT_NAME_NOGLOB, &unit); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + u = unit; } else u = SPECIAL_DEFAULT_TARGET; @@ -1882,7 +1886,6 @@ static int list_machines(sd_bus *bus, char **args) { static int get_default(sd_bus *bus, char **args) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *_path = NULL; const char *path; int r; @@ -1894,6 +1897,8 @@ static int get_default(sd_bus *bus, char **args) { path = _path; } else { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -1938,9 +1943,9 @@ static int set_default(sd_bus *bus, char **args) { unsigned n_changes = 0; int r; - unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target"); - if (!unit) - return log_oom(); + r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".target", &unit); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); if (!bus || avoid_bus()) { r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes); @@ -1952,34 +1957,26 @@ static int set_default(sd_bus *bus, char **args) { r = 0; } else { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - r = sd_bus_message_new_method_call( + polkit_agent_open_if_enabled(); + + r = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "SetDefaultTarget"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(m, "sb", unit, 1); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_call(bus, m, 0, &error, &reply); + "SetDefaultTarget", + &error, + &reply, + "sb", unit, 1); if (r < 0) { log_error("Failed to set default target: %s", bus_error_message(&error, -r)); return r; } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; @@ -2130,7 +2127,6 @@ static int list_jobs(sd_bus *bus, char **args) { } static int cancel_job(sd_bus *bus, char **args) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; char **name; int r = 0; @@ -2139,8 +2135,10 @@ static int cancel_job(sd_bus *bus, char **args) { if (strv_length(args) <= 1) return daemon_reload(bus, args); + polkit_agent_open_if_enabled(); + STRV_FOREACH(name, args+1) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; uint32_t id; int q; @@ -2148,25 +2146,15 @@ static int cancel_job(sd_bus *bus, char **args) { if (q < 0) return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name); - q = sd_bus_message_new_method_call( + q = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "CancelJob"); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (q < 0) - return bus_log_create_error(1); - - q = sd_bus_message_append(m, "u", id); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_call(bus, m, 0, &error, NULL); + "CancelJob", + &error, + NULL, + "u", id); if (q < 0) { log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q)); if (r == 0) @@ -2250,12 +2238,13 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un return 0; } -static int unit_find_paths(sd_bus *bus, - const char *unit_name, - bool avoid_bus_cache, - LookupPaths *lp, - char **fragment_path, - char ***dropin_paths) { +static int unit_find_paths( + sd_bus *bus, + const char *unit_name, + bool avoid_bus_cache, + LookupPaths *lp, + char **fragment_path, + char ***dropin_paths) { _cleanup_free_ char *path = NULL; _cleanup_strv_free_ char **dropins = NULL; @@ -2273,7 +2262,7 @@ static int unit_find_paths(sd_bus *bus, assert(fragment_path); assert(lp); - if (!avoid_bus_cache && !unit_name_is_template(unit_name)) { + if (!avoid_bus_cache && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *unit_load_error = NULL; _cleanup_free_ char *unit = NULL; @@ -2339,24 +2328,23 @@ static int unit_find_paths(sd_bus *bus, names = set_new(NULL); if (!names) - return -ENOMEM; + return log_oom(); r = set_put(names, unit_name); if (r < 0) - return r; + return log_error_errno(r, "Failed to add unit name: %m"); r = unit_file_find_path(lp, unit_name, &path); if (r < 0) return r; if (r == 0) { - _cleanup_free_ char *template; + _cleanup_free_ char *template = NULL; - template = unit_name_template(unit_name); - if (!template) - return log_oom(); - - if (!streq(template, unit_name)) { + r = unit_name_template(unit_name, &template); + if (r < 0 && r != -EINVAL) + return log_error_errno(r, "Failed to determine template name: %m"); + if (r >= 0) { r = unit_file_find_path(lp, template, &path); if (r < 0) return r; @@ -2398,9 +2386,9 @@ static int check_one_unit(sd_bus *bus, const char *name, const char *good_states assert(name); - n = unit_name_mangle(name, MANGLE_NOGLOB); - if (!n) - return log_oom(); + r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); /* We don't use unit_dbus_path_from_name() directly since we * don't want to load the unit if it isn't loaded. */ @@ -2455,9 +2443,9 @@ static int check_triggering_units( char **i; int r; - n = unit_name_mangle(name, MANGLE_NOGLOB); - if (!n) - return log_oom(); + r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); path = unit_dbus_path_from_name(n); if (!path) @@ -2556,7 +2544,7 @@ static int start_unit_one( sd_bus_error *error, BusWaitForJobs *w) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; const char *path; int r; @@ -2567,25 +2555,15 @@ static int start_unit_one( log_debug("Calling manager for %s on %s, %s", method, name, mode); - r = sd_bus_message_new_method_call( + r = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - method); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(m, "ss", name, mode); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_call(bus, m, 0, error, &reply); + method, + error, + &reply, + "ss", name, mode); if (r < 0) { const char *verb; @@ -2621,17 +2599,17 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r _cleanup_strv_free_ char **mangled = NULL, **globs = NULL; char **name; - int r = 0, i; + int r, i; STRV_FOREACH(name, names) { char *t; if (suffix) - t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix); + r = unit_name_mangle_with_suffix(*name, UNIT_NAME_GLOB, suffix, &t); else - t = unit_name_mangle(*name, MANGLE_GLOB); - if (!t) - return log_oom(); + r = unit_name_mangle(*name, UNIT_NAME_GLOB, &t); + if (r < 0) + return log_error_errno(r, "Failed to mangle name: %m"); if (string_is_glob(t)) r = strv_consume(&globs, t); @@ -2648,7 +2626,7 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r _cleanup_free_ UnitInfo *unit_infos = NULL; if (!bus) - return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented."); + return log_error_errno(EOPNOTSUPP, "Unit name globbing without bus is not implemented."); r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply); if (r < 0) @@ -2674,10 +2652,10 @@ static const struct { [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" }, [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" }, [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" }, - [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" }, - [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" }, - [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" }, - [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" }, + [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, + [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, + [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, + [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" }, [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" }, [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" }, [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" }, @@ -2881,6 +2859,9 @@ static int check_inhibitors(sd_bus *bus, enum action a) { if (!sv) return log_oom(); + if ((pid_t) pid < 0) + return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid); + if (!strv_contains(sv, a == ACTION_HALT || a == ACTION_POWEROFF || @@ -2892,7 +2873,7 @@ static int check_inhibitors(sd_bus *bus, enum action a) { user = uid_to_name(uid); log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".", - who, pid, strna(comm), strna(user), why); + who, (pid_t) pid, strna(comm), strna(user), why); c++; } @@ -2938,6 +2919,46 @@ static int check_inhibitors(sd_bus *bus, enum action a) { #endif } +static int prepare_firmware_setup(sd_bus *bus) { +#ifdef HAVE_LOGIND + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; +#endif + int r; + + if (!arg_firmware_setup) + return 0; + + if (arg_transport == BUS_TRANSPORT_LOCAL) { + + r = efi_set_reboot_to_firmware(true); + if (r < 0) + log_debug_errno(r, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m"); + else + return r; + } + +#ifdef HAVE_LOGIND + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetRebootToFirmwareSetup", + &error, + NULL, + "b", true); + if (r < 0) { + log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r)); + return r; + } + + return 0; +#else + log_error("Cannot remotely indicate to EFI to boot into setup mode."); + return -EINVAL; +#endif +} + static int start_special(sd_bus *bus, char **args) { enum action a; int r; @@ -2955,6 +2976,10 @@ static int start_special(sd_bus *bus, char **args) { return -EPERM; } + r = prepare_firmware_setup(bus); + if (r < 0) + return r; + if (a == ACTION_REBOOT && args[1]) { r = update_reboot_param_file(args[1]); if (r < 0) @@ -2983,7 +3008,7 @@ static int start_special(sd_bus *bus, char **args) { a == ACTION_HIBERNATE || a == ACTION_HYBRID_SLEEP)) { r = reboot_with_logind(bus, a); - if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS)) + if (r >= 0 || IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) return r; } @@ -3029,7 +3054,6 @@ static int check_unit_failed(sd_bus *bus, char **args) { } static int kill_unit(sd_bus *bus, char **args) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_strv_free_ char **names = NULL; char **name; int r, q; @@ -3047,27 +3071,17 @@ static int kill_unit(sd_bus *bus, char **args) { log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - q = sd_bus_message_new_method_call( + q = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "KillUnit"); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_call(bus, m, 0, &error, NULL); + "KillUnit", + &error, + NULL, + "ssi", *names, arg_kill_who, arg_signal); if (q < 0) { log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q)); if (r == 0) @@ -3233,6 +3247,7 @@ typedef struct UnitStatusInfo { /* CGroup */ uint64_t memory_current; uint64_t memory_limit; + uint64_t cpu_usage_nsec; LIST_HEAD(ExecStatusInfo, exec); } UnitStatusInfo; @@ -3503,6 +3518,11 @@ static void print_status_info( printf("\n"); } + if (i->cpu_usage_nsec != (uint64_t) -1) { + char buf[FORMAT_TIMESPAN_MAX]; + printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC)); + } + if (i->control_group && (i->main_pid > 0 || i->control_pid > 0 || ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) { @@ -3721,6 +3741,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo * i->memory_current = u; else if (streq(name, "MemoryLimit")) i->memory_limit = u; + else if (streq(name, "CPUUsageNSec")) + i->cpu_usage_nsec = u; break; } @@ -4194,6 +4216,7 @@ static int show_one( UnitStatusInfo info = { .memory_current = (uint64_t) -1, .memory_limit = (uint64_t) -1, + .cpu_usage_nsec = (uint64_t) -1, }; ExecStatusInfo *p; int r; @@ -4446,6 +4469,12 @@ static int show(sd_bus *bus, char **args) { if (show_properties) pager_open_if_enabled(); + if (show_status) + /* Increase max number of open files to 16K if we can, we + * might needs this when browsing journal files, which might + * be split up into many files. */ + setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384)); + /* If no argument is specified inspect the manager itself */ if (show_properties && strv_length(args) <= 1) @@ -4552,6 +4581,23 @@ static int init_home_and_lookup_paths(char **user_home, char **user_runtime, Loo return 0; } +static int cat_file(const char *filename, bool newline) { + _cleanup_close_ int fd; + + fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return -errno; + + printf("%s%s# %s%s\n", + newline ? "\n" : "", + ansi_highlight_blue(), + filename, + ansi_highlight_off()); + fflush(stdout); + + return copy_bytes(fd, STDOUT_FILENO, (off_t) -1, false); +} + static int cat(sd_bus *bus, char **args) { _cleanup_free_ char *user_home = NULL; _cleanup_free_ char *user_runtime = NULL; @@ -4559,7 +4605,7 @@ static int cat(sd_bus *bus, char **args) { _cleanup_strv_free_ char **names = NULL; char **name; bool first = true, avoid_bus_cache; - int r = 0; + int r; assert(args); @@ -4597,36 +4643,19 @@ static int cat(sd_bus *bus, char **args) { puts(""); if (fragment_path) { - printf("%s# %s%s\n", - ansi_highlight_blue(), - fragment_path, - ansi_highlight_off()); - fflush(stdout); - - r = copy_file_fd(fragment_path, STDOUT_FILENO, false); - if (r < 0) { - log_warning_errno(r, "Failed to cat %s: %m", fragment_path); - continue; - } + r = cat_file(fragment_path, false); + if (r < 0) + return log_warning_errno(r, "Failed to cat %s: %m", fragment_path); } STRV_FOREACH(path, dropin_paths) { - printf("%s%s# %s%s\n", - isempty(fragment_path) && path == dropin_paths ? "" : "\n", - ansi_highlight_blue(), - *path, - ansi_highlight_off()); - fflush(stdout); - - r = copy_file_fd(*path, STDOUT_FILENO, false); - if (r < 0) { - log_warning_errno(r, "Failed to cat %s: %m", *path); - continue; - } + r = cat_file(*path, path == dropin_paths); + if (r < 0) + return log_warning_errno(r, "Failed to cat %s: %m", *path); } } - return r < 0 ? r : 0; + return 0; } static int set_property(sd_bus *bus, char **args) { @@ -4648,13 +4677,9 @@ static int set_property(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + r = unit_name_mangle(args[1], UNIT_NAME_NOGLOB, &n); if (r < 0) - return bus_log_create_error(r); - - n = unit_name_mangle(args[1], MANGLE_NOGLOB); - if (!n) - return log_oom(); + return log_error_errno(r, "Failed to mangle unit name: %m"); r = sd_bus_message_append(m, "sb", n, arg_runtime); if (r < 0) @@ -4693,39 +4718,32 @@ static int set_property(sd_bus *bus, char **args) { static int snapshot(sd_bus *bus, char **args) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ char *n = NULL, *id = NULL; const char *path; int r; polkit_agent_open_if_enabled(); - if (strv_length(args) > 1) - n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot"); - else + if (strv_length(args) > 1) { + r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".snapshot", &n); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + } else { n = strdup(""); - if (!n) - return log_oom(); + if (!n) + return log_oom(); + } - r = sd_bus_message_new_method_call( + r = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "CreateSnapshot"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(m, "sb", n, false); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_call(bus, m, 0, &error, &reply); + "CreateSnapshot", + &error, + &reply, + "sb", n, false); if (r < 0) { log_error("Failed to create snapshot: %s", bus_error_message(&error, r)); return r; @@ -4755,7 +4773,6 @@ static int snapshot(sd_bus *bus, char **args) { } static int delete_snapshot(sd_bus *bus, char **args) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_strv_free_ char **names = NULL; char **name; int r; @@ -4769,28 +4786,18 @@ static int delete_snapshot(sd_bus *bus, char **args) { log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; int q; - q = sd_bus_message_new_method_call( + q = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "RemoveSnapshot"); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_message_append(m, "s", *name); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_call(bus, m, 0, &error, NULL); + "RemoveSnapshot", + &error, + NULL, + "s", *name); if (q < 0) { log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q)); if (r == 0) @@ -4803,7 +4810,6 @@ static int delete_snapshot(sd_bus *bus, char **args) { static int daemon_reload(sd_bus *bus, char **args) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; const char *method; int r; @@ -4829,21 +4835,15 @@ static int daemon_reload(sd_bus *bus, char **args) { /* "daemon-reload" */ "Reload"; } - r = sd_bus_message_new_method_call( + r = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - method); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_call(bus, m, 0, &error, NULL); + method, + &error, + NULL, + NULL); if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL) /* There's always a fallback possible for * legacy actions. */ @@ -4859,7 +4859,6 @@ static int daemon_reload(sd_bus *bus, char **args) { } static int reset_failed(sd_bus *bus, char **args) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_strv_free_ char **names = NULL; char **name; int r, q; @@ -4874,27 +4873,17 @@ static int reset_failed(sd_bus *bus, char **args) { log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - q = sd_bus_message_new_method_call( + q = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "ResetFailedUnit"); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_message_append(m, "s", *name); - if (q < 0) - return bus_log_create_error(q); - - q = sd_bus_call(bus, m, 0, &error, NULL); + "ResetFailedUnit", + &error, + NULL, + "s", *name); if (q < 0) { log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q)); if (r == 0) @@ -5013,6 +5002,8 @@ static int set_environment(sd_bus *bus, char **args) { assert(bus); assert(args); + polkit_agent_open_if_enabled(); + method = streq(args[0], "set-environment") ? "SetEnvironment" : "UnsetEnvironment"; @@ -5027,10 +5018,6 @@ static int set_environment(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - r = sd_bus_message_append_strv(m, args + 1); if (r < 0) return bus_log_create_error(r); @@ -5052,6 +5039,8 @@ static int import_environment(sd_bus *bus, char **args) { assert(bus); assert(args); + polkit_agent_open_if_enabled(); + r = sd_bus_message_new_method_call( bus, &m, @@ -5062,10 +5051,6 @@ static int import_environment(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - if (strv_isempty(args + 1)) r = sd_bus_message_append_strv(m, environ); else { @@ -5114,7 +5099,7 @@ static int import_environment(sd_bus *bus, char **args) { static int enable_sysv_units(const char *verb, char **args) { int r = 0; -#if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG) +#if defined(HAVE_SYSV_COMPAT) unsigned f = 0; _cleanup_lookup_paths_free_ LookupPaths paths = {}; @@ -5129,7 +5114,7 @@ static int enable_sysv_units(const char *verb, char **args) { /* Processes all SysV units, and reshuffles the array so that * afterwards only the native units remain */ - r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL); + r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, arg_root, NULL, NULL, NULL); if (r < 0) return r; @@ -5139,7 +5124,7 @@ static int enable_sysv_units(const char *verb, char **args) { _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL; bool found_native = false, found_sysv; unsigned c = 1; - const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL }; + const char *argv[6] = { ROOTLIBEXECDIR "/systemd-sysv-install", NULL, NULL, NULL, NULL }; char **k; int j; pid_t pid; @@ -5165,7 +5150,10 @@ static int enable_sysv_units(const char *verb, char **args) { break; } - if (found_native) + /* If we have both a native unit and a SysV script, + * enable/disable them both (below); for is-enabled, prefer the + * native unit */ + if (found_native && streq(verb, "is-enabled")) continue; p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name); @@ -5177,15 +5165,16 @@ static int enable_sysv_units(const char *verb, char **args) { if (!found_sysv) continue; - log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name); + if (found_native) + log_info("Synchronizing state of %s with SysV init with %s...", name, argv[0]); + else + log_info("%s is not a native service, redirecting to systemd-sysv-install", name); if (!isempty(arg_root)) argv[c++] = q = strappend("--root=", arg_root); + argv[c++] = verb; argv[c++] = basename(p); - argv[c++] = - streq(verb, "enable") ? "on" : - streq(verb, "disable") ? "off" : "--level=5"; argv[c] = NULL; l = strv_join((char**)argv, " "); @@ -5201,6 +5190,7 @@ static int enable_sysv_units(const char *verb, char **args) { /* Child */ execv(argv[0], (char**) argv); + log_error("Failed to execute %s: %m", argv[0]); _exit(EXIT_FAILURE); } @@ -5226,6 +5216,9 @@ static int enable_sysv_units(const char *verb, char **args) { } else return -EPROTO; + if (found_native) + continue; + /* Remove this entry, so that we don't try enabling it as native unit */ assert(f > 0); f--; @@ -5239,25 +5232,29 @@ static int enable_sysv_units(const char *verb, char **args) { static int mangle_names(char **original_names, char ***mangled_names) { char **i, **l, **name; + int r; - l = new(char*, strv_length(original_names) + 1); + l = i = new(char*, strv_length(original_names) + 1); if (!l) return log_oom(); - i = l; STRV_FOREACH(name, original_names) { /* When enabling units qualified path names are OK, * too, hence allow them explicitly. */ - if (is_path(*name)) + if (is_path(*name)) { *i = strdup(*name); - else - *i = unit_name_mangle(*name, MANGLE_NOGLOB); - - if (!*i) { - strv_free(l); - return log_oom(); + if (!*i) { + strv_free(l); + return log_oom(); + } + } else { + r = unit_name_mangle(*name, UNIT_NAME_NOGLOB, i); + if (r < 0) { + strv_free(l); + return log_error_errno(r, "Failed to mangle unit name: %m"); + } } i++; @@ -5370,10 +5367,6 @@ static int enable_unit(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - r = sd_bus_message_append_strv(m, names); if (r < 0) return bus_log_create_error(r); @@ -5406,7 +5399,7 @@ static int enable_unit(sd_bus *bus, char **args) { return bus_log_parse_error(r); } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); if (r < 0) return r; @@ -5428,6 +5421,18 @@ static int enable_unit(sd_bus *bus, char **args) { "3) A unit may be started when needed via activation (socket, path, timer,\n" " D-Bus, udev, scripted systemctl call, ...).\n"); + if (arg_now && n_changes > 0 && STR_IN_SET(args[0], "enable", "disable", "mask")) { + char *new_args[n_changes + 2]; + unsigned i; + + new_args[0] = streq(args[0], "enable") ? (char *)"start" : (char *)"stop"; + for (i = 0; i < n_changes; i++) + new_args[i + 1] = basename(changes[i].path); + new_args[i + 1] = NULL; + + r = start_unit(bus, new_args); + } + finish: unit_file_changes_free(changes, n_changes); @@ -5444,9 +5449,9 @@ static int add_dependency(sd_bus *bus, char **args) { if (!args[1]) return 0; - target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target"); - if (!target) - return log_oom(); + r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".target", &target); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); r = mangle_names(args+2, &names); if (r < 0) @@ -5489,10 +5494,6 @@ static int add_dependency(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - r = sd_bus_message_append_strv(m, names); if (r < 0) return bus_log_create_error(r); @@ -5507,7 +5508,7 @@ static int add_dependency(sd_bus *bus, char **args) { return r; } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; @@ -5539,41 +5540,29 @@ static int preset_all(sd_bus *bus, char **args) { r = 0; } else { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; polkit_agent_open_if_enabled(); - r = sd_bus_message_new_method_call( + r = sd_bus_call_method( bus, - &m, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "PresetAllUnitFiles"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append( - m, + "PresetAllUnitFiles", + &error, + &reply, "sbb", unit_file_preset_mode_to_string(arg_preset_mode), arg_runtime, arg_force); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_call(bus, m, 0, &error, &reply); if (r < 0) { log_error("Failed to execute operation: %s", bus_error_message(&error, r)); return r; } - r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet); + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; @@ -5756,10 +5745,10 @@ static int get_file_to_edit(const char *name, const char *user_home, const char if (arg_runtime) { if (access(path, F_OK) >= 0) - return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.", + return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path); if (path2 && access(path2, F_OK) >= 0) - return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.", + return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path2); *ret_path = run; run = NULL; @@ -5771,7 +5760,6 @@ static int get_file_to_edit(const char *name, const char *user_home, const char return 0; } - static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) { char *tmp_new_path, *ending; char *tmp_tmp_path; @@ -5798,12 +5786,14 @@ static int unit_file_create_dropin(const char *unit_name, const char *user_home, return 0; } -static int unit_file_create_copy(const char *unit_name, - const char *fragment_path, - const char *user_home, - const char *user_runtime, - char **ret_new_path, - char **ret_tmp_path) { +static int unit_file_create_copy( + const char *unit_name, + const char *fragment_path, + const char *user_home, + const char *user_runtime, + char **ret_new_path, + char **ret_tmp_path) { + char *tmp_new_path; char *tmp_tmp_path; int r; @@ -5859,9 +5849,8 @@ static int run_editor(char **paths) { if (pid == 0) { const char **args; - char **backup_editors = STRV_MAKE("nano", "vim", "vi"); char *editor; - char **tmp_path, **original_path, **p; + char **tmp_path, **original_path, *p; unsigned i = 1; size_t argc; @@ -5890,9 +5879,9 @@ static int run_editor(char **paths) { execvp(editor, (char* const*) args); } - STRV_FOREACH(p, backup_editors) { - args[0] = *p; - execvp(*p, (char* const*) args); + FOREACH_STRING(p, "editor", "nano", "vim", "vi") { + args[0] = p; + execvp(p, (char* const*) args); /* We do not fail if the editor doesn't exist * because we want to try each one of them before * failing. @@ -5903,7 +5892,7 @@ static int run_editor(char **paths) { } } - log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR or $EDITOR or $VISUAL."); + log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL."); _exit(EXIT_FAILURE); } @@ -6049,6 +6038,7 @@ static void systemctl_help(void) { " When shutting down or sleeping, ignore inhibitors\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" + " --now Start or stop unit in addition to enabling or disabling it\n" " -q --quiet Suppress output\n" " --no-block Do not wait until operation finished\n" " --no-wall Don't send wall message before halt/power-off/reboot\n" @@ -6067,6 +6057,7 @@ static void systemctl_help(void) { " -o --output=STRING Change journal output mode (short, short-iso,\n" " short-precise, short-monotonic, verbose,\n" " export, json, json-pretty, json-sse, cat)\n" + " --firmware-setup Tell the firmware to show the setup menu on next boot\n" " --plain Print unit dependencies as a list instead of a tree\n\n" "Unit Commands:\n" " list-units [PATTERN...] List loaded units\n" @@ -6246,6 +6237,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { ARG_STATE, ARG_JOB_MODE, ARG_PRESET_MODE, + ARG_FIRMWARE_SETUP, + ARG_NOW, }; static const struct option options[] = { @@ -6288,6 +6281,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "state", required_argument, NULL, ARG_STATE }, { "recursive", no_argument, NULL, 'r' }, { "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, + { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP }, + { "now", no_argument, NULL, ARG_NOW }, {} }; @@ -6528,6 +6523,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { arg_plain = true; break; + case ARG_FIRMWARE_SETUP: + arg_firmware_setup = true; + break; + case ARG_STATE: { const char *word, *state; size_t size; @@ -6564,6 +6563,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { break; + case ARG_NOW: + arg_now = true; + break; + case '?': return -EINVAL; @@ -7207,51 +7210,6 @@ found: return verb->dispatch(bus, argv + optind); } -static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) { - - struct sd_shutdown_command c = { - .usec = t, - .mode = mode, - .dry_run = dry_run, - .warn_wall = warn, - }; - - union sockaddr_union sockaddr = { - .un.sun_family = AF_UNIX, - .un.sun_path = "/run/systemd/shutdownd", - }; - - struct iovec iovec[2] = {{ - .iov_base = (char*) &c, - .iov_len = offsetof(struct sd_shutdown_command, wall_message), - }}; - - struct msghdr msghdr = { - .msg_name = &sockaddr, - .msg_namelen = offsetof(struct sockaddr_un, sun_path) - + strlen("/run/systemd/shutdownd"), - .msg_iov = iovec, - .msg_iovlen = 1, - }; - - _cleanup_close_ int fd; - - fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); - if (fd < 0) - return -errno; - - if (!isempty(message)) { - iovec[1].iov_base = (char*) message; - iovec[1].iov_len = strlen(message); - msghdr.msg_iovlen++; - } - - if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) - return -errno; - - return 0; -} - static int reload_with_fallback(sd_bus *bus) { if (bus) { @@ -7359,23 +7317,68 @@ static int halt_main(sd_bus *bus) { } if (arg_when > 0) { - _cleanup_free_ char *m; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_close_unref_ sd_bus *b = NULL; + _cleanup_free_ char *m = NULL; + + if (avoid_bus()) { + log_error("Unable to perform operation without bus connection."); + return -ENOSYS; + } + + r = sd_bus_open_system(&b); + if (r < 0) + return log_error_errno(r, "Unable to open system bus: %m"); m = strv_join(arg_wall, " "); if (!m) return log_oom(); - r = send_shutdownd(arg_when, - arg_action == ACTION_HALT ? 'H' : - arg_action == ACTION_POWEROFF ? 'P' : - arg_action == ACTION_KEXEC ? 'K' : - 'r', - arg_dry, - !arg_no_wall, - m); + r = sd_bus_set_property( + b, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "WallMessage", + &error, + "s", m); + if (r < 0) { + log_warning_errno(r, "Failed to set WallMessage property in logind: %s", + bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + + r = sd_bus_set_property( + b, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "EnableWallMessages", + &error, + "b", !arg_no_wall); + if (r < 0) { + log_warning_errno(r, "Failed to set EnableWallMessages property in logind: %s", + bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + r = sd_bus_call_method( + b, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ScheduleShutdown", + &error, + NULL, + "st", + arg_action == ACTION_HALT ? "halt" : + arg_action == ACTION_POWEROFF ? "poweroff" : + arg_action == ACTION_KEXEC ? "kexec" : + "reboot", + arg_when); if (r < 0) - log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m"); + log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", + bus_error_message(&error, r)); else { char date[FORMAT_TIMESTAMP_MAX]; @@ -7453,14 +7456,12 @@ int main(int argc, char*argv[]) { goto finish; } - /* Increase max number of open files to 16K if we can, we - * might needs this when browsing journal files, which might - * be split up into many files. */ - setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384)); - if (!avoid_bus()) r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus); + if (bus) + sd_bus_set_allow_interactive_authorization(bus, arg_ask_password); + /* systemctl_main() will print an error message for the bus * connection, but only if it needs to */ @@ -7493,8 +7494,19 @@ int main(int argc, char*argv[]) { break; case ACTION_CANCEL_SHUTDOWN: { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_close_unref_ sd_bus *b = NULL; _cleanup_free_ char *m = NULL; + if (avoid_bus()) { + log_error("Unable to perform operation without bus connection."); + return -ENOSYS; + } + + r = sd_bus_open_system(&b); + if (r < 0) + return log_error_errno(r, "Unable to open system bus: %m"); + if (arg_wall) { m = strv_join(arg_wall, " "); if (!m) { @@ -7503,9 +7515,45 @@ int main(int argc, char*argv[]) { } } - r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m); + r = sd_bus_set_property( + b, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "WallMessage", + &error, + "s", arg_wall); + if (r < 0) { + log_warning_errno(r, "Failed to set WallMessage property in logind: %s", + bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + + r = sd_bus_set_property( + b, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "EnableWallMessages", + &error, + "b", !arg_no_wall); + if (r < 0) { + log_warning_errno(r, "Failed to set EnableWallMessages property in logind: %s", + bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + + r = sd_bus_call_method( + b, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "CancelScheduledShutdown", + &error, + NULL, NULL); if (r < 0) - log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m"); + log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", + bus_error_message(&error, r)); break; } |