diff options
-rw-r--r-- | man/systemctl.xml | 12 | ||||
-rw-r--r-- | src/login/logind-dbus.c | 45 | ||||
-rw-r--r-- | src/login/org.freedesktop.login1.conf | 4 | ||||
-rw-r--r-- | src/login/org.freedesktop.login1.policy.in | 12 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 102 |
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); } |