summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mack <daniel@zonque.org>2015-04-23 16:03:02 +0200
committerDaniel Mack <daniel@zonque.org>2015-04-24 17:48:12 +0200
commitf0efea232a582660b25ee992853c78cf825721b6 (patch)
tree8df8b368f0f8f0f5db21b32ee1006b9128fa5792
parent867c37f6bb20886204679df9a43c973e2d7e44a5 (diff)
systemctl: talk to logind for scheduled shutdowns
Drop the code which communicates with shutdownd via its private socket, and use the functionality in logind instead. The code pathes which talk to logind have to create their own ad-hoc bus connection because by default, systemctl connects to systemd's private socket.
-rw-r--r--src/systemctl/systemctl.c160
1 files changed, 103 insertions, 57 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 38d15ff4ed..12126737fc 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -34,7 +34,6 @@
#include <stddef.h>
#include "sd-daemon.h"
-#include "sd-shutdown.h"
#include "sd-login.h"
#include "sd-bus.h"
#include "log.h"
@@ -7173,51 +7172,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) {
@@ -7325,23 +7279,68 @@ static int halt_main(sd_bus *bus) {
}
if (arg_when > 0) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_bus_close_unref_ sd_bus *b = NULL;
_cleanup_free_ char *m;
+ 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\n");
+
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];
@@ -7457,8 +7456,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\n");
+
if (arg_wall) {
m = strv_join(arg_wall, " ");
if (!m) {
@@ -7467,9 +7477,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;
}