#include "path-util.h"
#include "polkit.h"
#include "special.h"
+#include "systemd/sd-id128.h"
+#include "systemd/sd-messages.h"
#define BUS_MANAGER_INTERFACE \
" <interface name=\"org.freedesktop.login1.Manager\">\n" \
" <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
" <arg name=\"seat\" type=\"s\" direction=\"out\"/>\n" \
" <arg name=\"vtnr\" type=\"u\" direction=\"out\"/>\n" \
+ " <arg name=\"existing\" type=\"b\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"ReleaseSession\">\n" \
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
" <property name=\"DelayInhibited\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"InhibitDelayMaxUSec\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"HandlePowerKey\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"HandleSleepKey\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"HandleSuspendKey\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"HandleHibernateKey\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"HandleLidSwitch\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"PreparingForShutdown\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"PreparingForSleep\" type=\"b\" access=\"read\"/>\n" \
User *user = NULL;
const char *type, *class, *seat, *tty, *display, *remote_user, *remote_host, *service;
uint32_t uid, leader, audit_id = 0;
- dbus_bool_t remote, kill_processes;
+ dbus_bool_t remote, kill_processes, exists;
char **controllers = NULL, **reset_controllers = NULL;
SessionType t;
SessionClass c;
seat = session->seat ? session->seat->id : "";
vtnr = session->vtnr;
+ exists = true;
+
b = dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &session->id,
DBUS_TYPE_UNIX_FD, &fifo_fd,
DBUS_TYPE_STRING, &seat,
DBUS_TYPE_UINT32, &vtnr,
+ DBUS_TYPE_BOOLEAN, &exists,
DBUS_TYPE_INVALID);
free(p);
}
seat = s ? s->id : "";
+ exists = false;
b = dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &session->id,
DBUS_TYPE_UNIX_FD, &fifo_fd,
DBUS_TYPE_STRING, &seat,
DBUS_TYPE_UINT32, &vtnr,
+ DBUS_TYPE_BOOLEAN, &exists,
DBUS_TYPE_INVALID);
free(p);
goto fail;
}
+ /* Delay is only supported for shutdown/sleep */
+ if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) {
+ r = -EINVAL;
+ goto fail;
+ }
+
r = verify_polkit(connection, message,
- m == INHIBIT_BLOCK ?
- "org.freedesktop.login1.inhibit-block" :
- "org.freedesktop.login1.inhibit-delay", false, NULL, error);
+ w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
+ w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
+ w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
+ w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
+ w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
+ w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
+ "org.freedesktop.login1.inhibit-handle-lid-switch",
+ false, NULL, error);
if (r < 0)
goto fail;
}
static int have_multiple_sessions(
- DBusConnection *connection,
Manager *m,
- DBusMessage *message,
- DBusError *error) {
+ uid_t uid) {
Session *session;
Iterator i;
- unsigned long ul;
assert(m);
- ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
- if (ul == (unsigned long) -1)
- return -EIO;
-
/* Check for other users' sessions. Greeter sessions do not count. */
HASHMAP_FOREACH(session, m->sessions, i)
- if (session->class == SESSION_USER && session->user->uid != ul)
+ if (session->class == SESSION_USER && session->user->uid != uid)
return true;
return false;
const char *result;
DBusMessage *reply = NULL;
int r;
+ unsigned long ul;
assert(m);
assert(connection);
}
}
- r = have_multiple_sessions(connection, m, message, error);
+ ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
+ if (ul == (unsigned long) -1)
+ return -EIO;
+
+ r = have_multiple_sessions(m, (uid_t) ul);
if (r < 0)
return r;
multiple_sessions = r > 0;
- blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
+ blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, (uid_t) ul);
if (multiple_sessions) {
r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
return 0;
}
+static int bus_manager_log_shutdown(
+ Manager *m,
+ InhibitWhat w,
+ const char *unit_name) {
+
+ const char *p, *q;
+
+ assert(m);
+ assert(unit_name);
+
+ if (w != INHIBIT_SHUTDOWN)
+ return 0;
+
+ if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
+ p = "MESSAGE=System is powering down.";
+ q = "SHUTDOWN=power-off";
+ } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
+ p = "MESSAGE=System is halting.";
+ q = "SHUTDOWN=halt";
+ } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
+ p = "MESSAGE=System is rebooting.";
+ q = "SHUTDOWN=reboot";
+ } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
+ p = "MESSAGE=System is rebooting with kexec.";
+ q = "SHUTDOWN=kexec";
+ } else {
+ p = "MESSAGE=System is shutting down.";
+ q = NULL;
+ }
+
+ return log_struct(LOG_NOTICE, MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
+ p,
+ q, NULL);
+}
+
int bus_manager_shutdown_or_sleep_now_or_later(
Manager *m,
const char *unit_name,
delayed =
m->inhibit_delay_max > 0 &&
- manager_is_inhibited(m, w, INHIBIT_DELAY, NULL);
+ manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0);
if (delayed)
/* Shutdown is delayed, keep in mind what we
* want to do, and start a timeout */
r = delay_shutdown_or_sleep(m, w, unit_name);
- else
+ else {
+ bus_manager_log_shutdown(m, w, unit_name);
+
/* Shutdown is not delayed, execute it
* immediately */
r = send_start_unit(m->bus, unit_name, error);
+ }
return r;
}
bool multiple_sessions, blocked;
DBusMessage *reply = NULL;
int r;
+ unsigned long ul;
assert(m);
assert(connection);
return -ENOTSUP;
}
- r = have_multiple_sessions(connection, m, message, error);
+ ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
+ if (ul == (unsigned long) -1)
+ return -EIO;
+
+ r = have_multiple_sessions(m, (uid_t) ul);
if (r < 0)
return r;
multiple_sessions = r > 0;
- blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
+ blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, (uid_t) ul);
if (multiple_sessions) {
r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
{ "DelayInhibited", bus_manager_append_inhibited, "s", 0 },
{ "InhibitDelayMaxUSec", bus_property_append_usec, "t", offsetof(Manager, inhibit_delay_max) },
{ "HandlePowerKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_power_key) },
- { "HandleSleepKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_sleep_key) },
+ { "HandleSuspendKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_suspend_key) },
+ { "HandleHibernateKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_hibernate_key)},
{ "HandleLidSwitch", bus_manager_append_handle_button, "s", offsetof(Manager, handle_lid_switch) },
{ "PreparingForShutdown", bus_manager_append_preparing, "b", 0 },
{ "PreparingForSleep", bus_manager_append_preparing, "b", 0 },
/* Continue delay? */
delayed =
manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
- manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL);
+ manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL, false, false, 0);
if (delayed)
return 0;
+ bus_manager_log_shutdown(manager, manager->delayed_what, manager->delayed_unit);
+
/* Reset delay data */
unit_name = manager->delayed_unit;
manager->delayed_unit = NULL;