X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Flogind-dbus.c;h=af62d8782117796423eca411fefd54ec0e9b18c6;hb=877d54e9b09e093c2102f519a84e2a52637ae035;hp=f4b232b9ae2134cbb40346eddf5476614311e909;hpb=398f7c881b90d2ca4edafcb60dba3822eb9f73eb;p=elogind.git diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index f4b232b9a..af62d8782 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" \ @@ -98,6 +100,7 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -209,6 +212,8 @@ " \n" \ " \n" \ " \n" \ + " \n" \ + " \n" \ " \n" #define INTROSPECTION_BEGIN \ @@ -273,6 +278,22 @@ static int bus_manager_append_inhibited(DBusMessageIter *i, const char *property return 0; } +static int bus_manager_append_preparing(DBusMessageIter *i, const char *property, void *data) { + Manager *m = data; + dbus_bool_t b; + + assert(i); + assert(property); + + if (streq(property, "PreparingForShutdown")) + b = !!(m->delayed_what & INHIBIT_SHUTDOWN); + else + b = !!(m->delayed_what & INHIBIT_SLEEP); + + dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b); + return 0; +} + static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMessage **_reply) { Session *session = NULL; User *user = NULL; @@ -930,62 +951,40 @@ static int have_multiple_sessions( DBusMessage *message, DBusError *error) { - Session *s; + Session *session; + Iterator i; + unsigned long ul; assert(m); - if (hashmap_size(m->sessions) > 1) - return true; - - /* Hmm, there's only one session, but let's make sure it - * actually belongs to the user who is asking. If not, better - * be safe than sorry. */ - - s = hashmap_first(m->sessions); - if (s) { - unsigned long ul; - - ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error); - if (ul == (unsigned long) -1) - return -EIO; + ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error); + if (ul == (unsigned long) -1) + return -EIO; - return s->user->uid != ul; - } + /* 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) + return true; return false; } static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) { - DBusMessage *message, *reply; const char *mode = "replace"; - assert(connection); assert(unit_name); - message = dbus_message_new_method_call( + return bus_method_call_with_reply ( + connection, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", - "StartUnit"); - if (!message) - return -ENOMEM; - - if (!dbus_message_append_args(message, - DBUS_TYPE_STRING, &unit_name, - DBUS_TYPE_STRING, &mode, - DBUS_TYPE_INVALID)) { - dbus_message_unref(message); - return -ENOMEM; - } - - reply = dbus_connection_send_with_reply_and_block(connection, message, -1, error); - dbus_message_unref(message); - - if (!reply) - return -EIO; - - dbus_message_unref(reply); - return 0; + "StartUnit", + NULL, + NULL, + DBUS_TYPE_STRING, &unit_name, + DBUS_TYPE_STRING, &mode, + DBUS_TYPE_INVALID); } static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { @@ -1088,11 +1087,11 @@ static int bus_manager_can_shutdown_or_sleep( if (r > 0) result = "yes"; - else if (challenge) - result = "challenge"; - else - result = "no"; - } + else if (challenge) + result = "challenge"; + else + result = "no"; + } if (blocked) { r = verify_polkit(connection, message, action_ignore_inhibit, false, &challenge, error); @@ -1141,6 +1140,42 @@ 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_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(SD_MESSAGE_SHUTDOWN), + p, + q, NULL); +} + int bus_manager_shutdown_or_sleep_now_or_later( Manager *m, const char *unit_name, @@ -1163,10 +1198,13 @@ int bus_manager_shutdown_or_sleep_now_or_later( /* 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; } @@ -1273,6 +1311,8 @@ static const BusProperty bus_login_manager_properties[] = { { "HandlePowerKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_power_key) }, { "HandleSleepKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_sleep_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 }, { NULL, } }; @@ -1732,6 +1772,18 @@ static DBusHandlerResult manager_message_handler( if (!reply) goto oom; + } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions")) { + Session *session; + Iterator i; + + HASHMAP_FOREACH(session, m->sessions, i) + if (session_send_lock(session, true) < 0) + goto oom; + + reply = dbus_message_new_method_return(message); + if (!reply) + goto oom; + } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillSession")) { const char *swho; int32_t signo; @@ -2245,6 +2297,8 @@ int manager_dispatch_delayed(Manager *manager) { 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;