X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flogin%2Flogind-dbus.c;h=0960aab634c502207c39186e3ef9ffa2e6e0f263;hb=90527fbb2c48ffda5c6d8f232f8993a90b2632a4;hp=4326e5b87cf3c339638641629a7148a60ef1c605;hpb=7ba643863116cd0b5abf048e53321f93e5743f69;p=elogind.git diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 4326e5b87..0960aab63 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -102,6 +102,7 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -197,6 +198,7 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ @@ -220,6 +222,8 @@ " \n" \ " \n" \ " \n" \ + " \n" \ + " \n" \ " \n" \ " \n" \ " \n" @@ -415,8 +419,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess if (vtnr != 0) return -EINVAL; - } else if (!isempty(tty) && s && seat_is_vtconsole(s)) - return -EINVAL; + } if (s) { if (seat_can_multi_session(s)) { @@ -978,30 +981,56 @@ static int have_multiple_sessions( assert(m); - /* Check for other users' sessions. Greeter sessions do not count. */ + /* Check for other users' sessions. Greeter sessions do not + * count, and non-login sessions do not count either. */ HASHMAP_FOREACH(session, m->sessions, i) - if (session->class == SESSION_USER && session->user->uid != uid) + if (session->class == SESSION_USER && + (session->type == SESSION_TTY || session->type == SESSION_X11) && + session->user->uid != uid) return true; return false; } -static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) { - const char *mode = "replace"; +static int send_start_unit(Manager *m, const char *unit_name, bool send_resumed, DBusError *error) { + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; + const char *mode = "replace", *p; + int r; + char *c; + assert(m); assert(unit_name); - return bus_method_call_with_reply ( - connection, + r = bus_method_call_with_reply( + m->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", - NULL, - NULL, + &reply, + error, DBUS_TYPE_STRING, &unit_name, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); + if (r < 0) + return r; + + if (!dbus_message_get_args( + reply, + error, + DBUS_TYPE_OBJECT_PATH, &p, + DBUS_TYPE_INVALID)) + return -EINVAL; + + c = strdup(p); + if (!c) + return -ENOMEM; + + free(m->action_job); + m->action_job = c; + m->send_resumed_after_action_job = send_resumed; + + return 0; } static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { @@ -1011,8 +1040,7 @@ static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { }; dbus_bool_t active = _active; - DBusMessage *message; - int r = 0; + _cleanup_dbus_message_unref_ DBusMessage *message = NULL; assert(m); assert(w >= 0); @@ -1025,10 +1053,9 @@ static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID) || !dbus_connection_send(m->bus, message, NULL)) - r = -ENOMEM; + return -ENOMEM; - dbus_message_unref(message); - return r; + return 0; } static int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, const char *unit_name) { @@ -1222,6 +1249,7 @@ int bus_manager_shutdown_or_sleep_now_or_later( assert(unit_name); assert(w >= 0); assert(w <= _INHIBIT_WHAT_MAX); + assert(!m->action_job); delayed = m->inhibit_delay_max > 0 && @@ -1236,7 +1264,7 @@ int bus_manager_shutdown_or_sleep_now_or_later( /* Shutdown is not delayed, execute it * immediately */ - r = send_start_unit(m->bus, unit_name, error); + r = send_start_unit(m, unit_name, w & INHIBIT_SLEEP, error); } return r; @@ -1274,6 +1302,9 @@ static int bus_manager_do_shutdown_or_sleep( assert(error); assert(_reply); + if (m->action_job || m->delayed_unit) + return -EALREADY; + if (!dbus_message_get_args( message, error, @@ -1340,7 +1371,7 @@ static int bus_manager_do_shutdown_or_sleep( return 0; } -static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_button, handle_button, HandleButton); +static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_action, handle_action, HandleAction); static const BusProperty bus_login_manager_properties[] = { { "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_path), true }, @@ -1356,10 +1387,12 @@ static const BusProperty bus_login_manager_properties[] = { { "BlockInhibited", bus_manager_append_inhibited, "s", 0 }, { "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) }, - { "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) }, + { "HandlePowerKey", bus_manager_append_handle_action, "s", offsetof(Manager, handle_power_key) }, + { "HandleSuspendKey", bus_manager_append_handle_action, "s", offsetof(Manager, handle_suspend_key) }, + { "HandleHibernateKey", bus_manager_append_handle_action, "s", offsetof(Manager, handle_hibernate_key)}, + { "HandleLidSwitch", bus_manager_append_handle_action, "s", offsetof(Manager, handle_lid_switch) }, + { "IdleAction", bus_manager_append_handle_action, "s", offsetof(Manager, idle_action) }, + { "IdleActionUSec", bus_property_append_usec, "t", offsetof(Manager, idle_action_usec) }, { "PreparingForShutdown", bus_manager_append_preparing, "b", 0 }, { "PreparingForSleep", bus_manager_append_preparing, "b", 0 }, { NULL, } @@ -1821,8 +1854,10 @@ static DBusHandlerResult manager_message_handler( if (!reply) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions")) { - r = session_send_lock_all(m, true); + } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions") || + dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSessions")) { + + r = session_send_lock_all(m, streq(dbus_message_get_member(message), "LockSessions")); if (r < 0) bus_send_error_reply(connection, message, NULL, r); @@ -2277,8 +2312,8 @@ static DBusHandlerResult manager_message_handler( } if (reply) { - if (!dbus_connection_send(connection, reply, NULL)) - goto oom; + if (!bus_maybe_send_reply(connection, message, reply)) + goto oom; dbus_message_unref(reply); } @@ -2321,6 +2356,31 @@ DBusHandlerResult bus_message_filter( log_error("Failed to parse Released message: %s", bus_error_message(&error)); else manager_cgroup_notify_empty(m, cgroup); + + } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) { + uint32_t id; + const char *path, *result, *unit; + + if (!dbus_message_get_args(message, &error, + DBUS_TYPE_UINT32, &id, + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_STRING, &unit, + DBUS_TYPE_STRING, &result, + DBUS_TYPE_INVALID)) + log_error("Failed to parse JobRemoved message: %s", bus_error_message(&error)); + else if (m->action_job && streq(m->action_job, path)) { + log_info("Action is complete, result is '%s'.", result); + free(m->action_job); + m->action_job = NULL; + + if (m->send_resumed_after_action_job) { + _cleanup_dbus_message_unref_ DBusMessage *s = NULL; + + s = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Resumed"); + if (s) + dbus_connection_send(m->bus, s, NULL); + } + } } dbus_error_free(&error); @@ -2370,21 +2430,21 @@ int manager_dispatch_delayed(Manager *manager) { bus_manager_log_shutdown(manager, manager->delayed_what, manager->delayed_unit); + /* Tell people about it */ + send_prepare_for(manager, manager->delayed_what, false); + /* Reset delay data */ unit_name = manager->delayed_unit; manager->delayed_unit = NULL; /* Actually do the shutdown */ dbus_error_init(&error); - r = send_start_unit(manager->bus, unit_name, &error); + r = send_start_unit(manager, unit_name, manager->delayed_what & INHIBIT_SLEEP, &error); if (r < 0) { log_warning("Failed to send delayed message: %s", bus_error_message_or_strerror(&error, -r)); dbus_error_free(&error); return r; } - /* Tell people about it */ - send_prepare_for(manager, manager->delayed_what, false); - return 1; }