summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Synacek <jsynacek@redhat.com>2015-08-24 14:54:22 +0200
committerJan Synacek <jsynacek@redhat.com>2015-08-25 13:52:44 +0200
commit9ef15026c0e7e6600372056c43442c99ec53746e (patch)
tree7b82f423cb3499c100c1d2a2b5540d336d4928f9
parent72aa2c2a2083362afda9f09805563848d54e31df (diff)
logind/systemctl: introduce SetWallMessage and --message
Enable unprivileged users to set wall message on a shutdown operation. When the message is set via the --message option, it is logged together with the default shutdown message. $ systemctl reboot --message "Applied kernel updates." $ journalctl -b -1 ... systemd-logind[27]: System is rebooting. (Applied kernel updates.) ...
-rw-r--r--man/systemctl.xml12
-rw-r--r--src/login/logind-dbus.c45
-rw-r--r--src/login/org.freedesktop.login1.conf4
-rw-r--r--src/login/org.freedesktop.login1.policy.in12
-rw-r--r--src/systemctl/systemctl.c102
5 files changed, 130 insertions, 45 deletions
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 0b5282ba21..20d143741b 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -474,6 +474,18 @@
</varlistentry>
<varlistentry>
+ <term><option>--message=</option></term>
+
+ <listitem>
+ <para>When used with <command>halt</command>,
+ <command>poweroff</command>, <command>reboot</command> or
+ <command>kexec</command>, set a short message explaining the reason
+ for the operation. The message will be logged together with the
+ default shutdown message.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--now</option></term>
<listitem>
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 992a9f5b4a..5b2b36b9c0 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1339,7 +1339,8 @@ static int bus_manager_log_shutdown(
InhibitWhat w,
const char *unit_name) {
- const char *p, *q;
+ const char *p;
+ const char *q;
assert(m);
assert(unit_name);
@@ -1364,6 +1365,9 @@ static int bus_manager_log_shutdown(
q = NULL;
}
+ if (m->wall_message)
+ p = strjoina(p, " (", m->wall_message, ")", NULL);
+
return log_struct(LOG_NOTICE,
LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
p,
@@ -2282,6 +2286,44 @@ static int method_can_reboot_to_firmware_setup(
return sd_bus_reply_method_return(message, "s", result);
}
+static int method_set_wall_message(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int r;
+ Manager *m = userdata;
+ char *wall_message;
+ bool enable_wall_messages;
+
+ assert(message);
+ assert(m);
+
+ r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-wall-message",
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = free_and_strdup(&m->wall_message, wall_message);
+ if (r < 0)
+ return log_oom();
+ m->enable_wall_messages = enable_wall_messages;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *who, *why, *what, *mode;
@@ -2463,6 +2505,7 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("SessionNew", "so", 0),
SD_BUS_SIGNAL("SessionRemoved", "so", 0),
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index d8deb7bc8b..1662d4c428 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -182,6 +182,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="SetWallMessage"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="AttachDevice"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index 83e7183323..23326bb79f 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -150,6 +150,7 @@
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.set-wall-message</annotate>
</action>
<action id="org.freedesktop.login1.power-off-multiple-sessions">
@@ -182,6 +183,7 @@
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.set-wall-message</annotate>
</action>
<action id="org.freedesktop.login1.reboot-multiple-sessions">
@@ -300,4 +302,14 @@
</defaults>
</action>
+ <action id="org.freedesktop.login1.set-wall-message">
+ <_description>Set a wall message</_description>
+ <_message>Authentication is required to set a wall message</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 1a9dbadbe1..3cb5f61868 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2794,6 +2794,33 @@ static int reboot_with_logind(sd_bus *bus, enum action a) {
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",
@@ -6260,6 +6287,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_PRESET_MODE,
ARG_FIRMWARE_SETUP,
ARG_NOW,
+ ARG_MESSAGE,
};
static const struct option options[] = {
@@ -6304,6 +6332,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "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 },
{}
};
@@ -6588,6 +6617,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_now = true;
break;
+ case ARG_MESSAGE:
+ if (strv_extend(&arg_wall, optarg) < 0)
+ return log_oom();
+ break;
+
case '?':
return -EINVAL;
@@ -7356,30 +7390,20 @@ static int halt_main(sd_bus *bus) {
if (!m)
return log_oom();
- 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_call_method(
+ b,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
- 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",
+ log_warning_errno(r, "Failed to set wall message, ignoring: %s",
bus_error_message(&error, r));
sd_bus_error_free(&error);
}
@@ -7537,30 +7561,20 @@ int main(int argc, char*argv[]) {
}
}
- 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_call_method(
+ b,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
- 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",
+ log_warning_errno(r, "Failed to set wall message, ignoring: %s",
bus_error_message(&error, r));
sd_bus_error_free(&error);
}