#include <stddef.h>
#include "sd-daemon.h"
-#include "sd-shutdown.h"
#include "sd-login.h"
#include "sd-bus.h"
#include "log.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;
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;
}
if (*p) {
- utmp_wall(p, NULL, NULL);
+ utmp_wall(p, NULL, NULL, NULL, NULL);
return;
}
}
if (!table[a])
return;
- utmp_wall(table[a], NULL, NULL);
+ utmp_wall(table[a], NULL, NULL, NULL, NULL);
}
static bool avoid_bus(void) {
return bus_log_create_error(r);
r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0) {
- log_error("Failed to list units: %s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
if (r < 0)
r = set_put(replies, reply);
if (r < 0) {
sd_bus_message_unref(reply);
- return r;
+ return log_oom();
}
if (arg_recursive) {
r = sd_get_machine_names(&machines);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to get machine names: %m");
STRV_FOREACH(i, machines) {
- _cleanup_bus_close_unref_ sd_bus *container = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
int k;
r = sd_bus_open_system_machine(&container, *i);
if (r < 0) {
- log_error_errno(r, "Failed to connect to container %s: %m", *i);
+ log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i);
continue;
}
r = set_put(replies, reply);
if (r < 0) {
sd_bus_message_unref(reply);
- return r;
+ return log_oom();
}
}
for (u = unit_infos; u < unit_infos + n; u++) {
_cleanup_strv_free_ char **triggered = NULL;
- dual_timestamp next = {};
+ dual_timestamp next = DUAL_TIMESTAMP_NULL;
usec_t m, last = 0;
if (!endswith(u->id, ".timer"))
"Requisite\0"
"RequisiteOverridable\0"
"Wants\0"
+ "ConsistsOf\0"
"BindsTo\0",
[DEPENDENCY_REVERSE] = "RequiredBy\0"
"RequiredByOverridable\0"
_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;
{}
};
+static void machine_info_clear(struct machine_info *info) {
+ if (info) {
+ free(info->name);
+ free(info->state);
+ free(info->control_group);
+ zero(*info);
+ }
+}
+
static void free_machines_list(struct machine_info *machine_infos, int n) {
int i;
if (!machine_infos)
return;
- for (i = 0; i < n; i++) {
- free(machine_infos[i].name);
- free(machine_infos[i].state);
- free(machine_infos[i].control_group);
- }
+ for (i = 0; i < n; i++)
+ machine_info_clear(&machine_infos[i]);
free(machine_infos);
}
}
static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
- _cleanup_bus_close_unref_ sd_bus *container = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *container = NULL;
int r;
assert(mi);
_cleanup_free_ char *hn = NULL;
size_t sz = 0;
char **i;
- int c = 0;
+ int c = 0, r;
hn = gethostname_malloc();
if (!hn)
c++;
}
- sd_get_machine_names(&m);
+ r = sd_get_machine_names(&m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get machine list: %m");
+
STRV_FOREACH(i, m) {
_cleanup_free_ char *class = NULL;
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);
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;
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;
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;
-
- template = unit_name_template(unit_name);
- if (!template)
- return log_oom();
+ _cleanup_free_ char *template = NULL;
- 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;
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. */
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)
_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);
return -EINVAL;
}
+ if (!strv_isempty(arg_wall)) {
+ _cleanup_free_ char *m;
+
+ m = strv_join(arg_wall, " ");
+ if (!m)
+ return log_oom();
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
+
+ if (r < 0) {
+ log_warning_errno(r, "Failed to set wall message, ignoring: %s",
+ bus_error_message(&error, r));
+ sd_bus_error_free(&error);
+ }
+ }
+
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
if (! dir || last) {
printf(dir ? " " : " Drop-In: ");
- free(dir);
- dir = NULL;
+ dir = mfree(dir);
if (path_get_parent(*dropin, &dir) < 0) {
log_oom();
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))) {
+ ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group) == 0))) {
unsigned c;
printf(" CGroup: %s\n", i->control_group);
}
}
- if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
+ if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
show_journal_by_unit(
stdout,
i->id,
SD_JOURNAL_LOCAL_ONLY,
arg_scope == UNIT_FILE_SYSTEM,
ellipsized);
- }
if (i->need_daemon_reload)
warn_unit_file_changed(i->id);
&error,
&reply,
"s", "");
- if (r < 0) {
- log_error("Failed to get properties: %s", bus_error_message(&error, r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
if (r < 0)
static int show_system_status(sd_bus *bus) {
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
_cleanup_free_ char *hn = NULL;
- struct machine_info mi = {};
+ _cleanup_(machine_info_clear) struct machine_info mi = {};
const char *on, *off;
int r;
show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
}
- free(mi.state);
- free(mi.control_group);
-
return 0;
}
if (r < 0)
return bus_log_create_error(r);
- n = unit_name_mangle(args[1], MANGLE_NOGLOB);
- if (!n)
- return log_oom();
+ r = unit_name_mangle(args[1], UNIT_NAME_NOGLOB, &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to mangle unit name: %m");
r = sd_bus_message_append(m, "sb", n, arg_runtime);
if (r < 0)
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_call_method(
bus,
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 = {};
/* 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;
_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;
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);
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, " ");
else if (pid == 0) {
/* Child */
+ (void) reset_all_signal_handlers();
+ (void) reset_signal_mask();
+
execv(argv[0], (char**) argv);
+ log_error("Failed to execute %s: %m", argv[0]);
_exit(EXIT_FAILURE);
}
} 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--;
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++;
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;
"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);
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)
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;
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;
assert(original_path);
assert(ret_tmp_fn);
- r = tempfn_random(new_path, &t);
+ r = tempfn_random(new_path, NULL, &t);
if (r < 0)
return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
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;
if (pid == 0) {
const char **args;
- char *editor;
+ char *editor, **editor_args = NULL;
char **tmp_path, **original_path, *p;
- unsigned i = 1;
+ unsigned n_editor_args = 0, i = 1;
size_t argc;
- argc = strv_length(paths)/2 + 1;
- args = newa(const char*, argc + 1);
+ (void) reset_all_signal_handlers();
+ (void) reset_signal_mask();
- args[0] = NULL;
- STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
- args[i] = *tmp_path;
- i++;
- }
- args[argc] = NULL;
+ argc = strv_length(paths)/2 + 1;
/* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
* If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
editor = getenv("VISUAL");
if (!isempty(editor)) {
- args[0] = editor;
- execvp(editor, (char* const*) args);
+ editor_args = strv_split(editor, WHITESPACE);
+ if (!editor_args) {
+ (void) log_oom();
+ _exit(EXIT_FAILURE);
+ }
+ n_editor_args = strv_length(editor_args);
+ argc += n_editor_args - 1;
+ }
+ args = newa(const char*, argc + 1);
+
+ if (n_editor_args > 0) {
+ args[0] = editor_args[0];
+ for (; i < n_editor_args; i++)
+ args[i] = editor_args[i];
}
- FOREACH_STRING(p, "nano", "vim", "vi") {
+ STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
+ args[i] = *tmp_path;
+ i++;
+ }
+ args[i] = NULL;
+
+ if (n_editor_args > 0)
+ execvp(args[0], (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
" 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"
ARG_JOB_MODE,
ARG_PRESET_MODE,
ARG_FIRMWARE_SETUP,
+ ARG_NOW,
+ ARG_MESSAGE,
};
static const struct option options[] = {
{ "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 },
+ { "message", required_argument, NULL, ARG_MESSAGE },
{}
};
break;
+ case ARG_NOW:
+ arg_now = true;
+ break;
+
+ case ARG_MESSAGE:
+ if (strv_extend(&arg_wall, optarg) < 0)
+ return log_oom();
+ break;
+
case '?':
return -EINVAL;
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) {
reboot(RB_POWER_OFF);
return -errno;
+ case ACTION_KEXEC:
case ACTION_REBOOT: {
_cleanup_free_ char *param = NULL;
}
if (arg_when > 0) {
- _cleanup_free_ char *m;
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_flush_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_call_method(
+ b,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
+ if (r < 0) {
+ log_warning_errno(r, "Failed to set wall message, ignoring: %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];
}
int main(int argc, char*argv[]) {
- _cleanup_bus_close_unref_ sd_bus *bus = NULL;
+ _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
int r;
setlocale(LC_ALL, "");
break;
case ACTION_CANCEL_SHUTDOWN: {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_flush_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) {
}
}
- r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
+ r = sd_bus_call_method(
+ b,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
+
+ if (r < 0) {
+ log_warning_errno(r, "Failed to set wall message, ignoring: %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;
}