X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Flogin%2Flogind-dbus.c;h=a7647e3c80a971c9482e1d74b274ecf7a7460376;hb=770858811930c0658b189d980159ea1ac5663467;hp=ae9671bb1ef3d9b7a19c041290560b5cabb67cde;hpb=b9c26b413497a0014ac2058a0ec04849a83df1ea;p=elogind.git diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ae9671bb1..a7647e3c8 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -31,6 +31,8 @@ #include "path-util.h" #include "polkit.h" #include "special.h" +#include "systemd/sd-id128.h" +#include "systemd/sd-messages.h" #define BUS_MANAGER_INTERFACE \ " \n" \ @@ -81,6 +83,7 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -208,7 +211,8 @@ " \n" \ " \n" \ " \n" \ - " \n" \ + " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -297,7 +301,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess 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; @@ -515,6 +519,8 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess seat = session->seat ? session->seat->id : ""; vtnr = session->vtnr; + exists = true; + b = dbus_message_append_args( reply, DBUS_TYPE_STRING, &session->id, @@ -523,6 +529,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess DBUS_TYPE_UNIX_FD, &fifo_fd, DBUS_TYPE_STRING, &seat, DBUS_TYPE_UINT32, &vtnr, + DBUS_TYPE_BOOLEAN, &exists, DBUS_TYPE_INVALID); free(p); @@ -639,6 +646,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess } seat = s ? s->id : ""; + exists = false; b = dbus_message_append_args( reply, DBUS_TYPE_STRING, &session->id, @@ -647,6 +655,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess DBUS_TYPE_UNIX_FD, &fifo_fd, DBUS_TYPE_STRING, &seat, DBUS_TYPE_UINT32, &vtnr, + DBUS_TYPE_BOOLEAN, &exists, DBUS_TYPE_INVALID); free(p); @@ -720,10 +729,21 @@ static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessa 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; @@ -944,24 +964,17 @@ static int flush_devices(Manager *m) { } 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; @@ -1048,6 +1061,7 @@ static int bus_manager_can_shutdown_or_sleep( const char *result; DBusMessage *reply = NULL; int r; + unsigned long ul; assert(m); assert(connection); @@ -1071,12 +1085,16 @@ static int bus_manager_can_shutdown_or_sleep( } } - 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); @@ -1138,6 +1156,41 @@ finish: 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, @@ -1154,16 +1207,19 @@ int bus_manager_shutdown_or_sleep_now_or_later( 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; } @@ -1185,6 +1241,7 @@ static int bus_manager_do_shutdown_or_sleep( bool multiple_sessions, blocked; DBusMessage *reply = NULL; int r; + unsigned long ul; assert(m); assert(connection); @@ -1214,12 +1271,16 @@ static int bus_manager_do_shutdown_or_sleep( 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); @@ -1268,7 +1329,8 @@ static const BusProperty bus_login_manager_properties[] = { { "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 }, @@ -2252,10 +2314,12 @@ int manager_dispatch_delayed(Manager *manager) { /* 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;