along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <errno.h>
+#include <string.h>
+
#include "logind.h"
#include "dbus-common.h"
#define BUS_MANAGER_INTERFACE \
" <interface name=\"org.freedesktop.login1.Manager\">\n" \
- " <method name=\"GetSeat\">\n" \
+ " <method name=\"GetSession\">\n" \
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
+ " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"GetUser\">\n" \
- " <arg name=\"uid\" type=\"t\" direction=\"in\"/>\n" \
+ " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
- " <method name=\"GetSession\">\n" \
+ " <method name=\"GetSeat\">\n" \
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
- " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
+ " <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
- " <method name=\"ListSeats\">\n" \
- " <arg name=\"seats\" type=\"a(so)\" direction=\"out\"/>\n" \
+ " <method name=\"ListSessions\">\n" \
+ " <arg name=\"sessions\" type=\"a(susso)\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"ListUsers\">\n" \
" <arg name=\"users\" type=\"a(uso)\" direction=\"out\"/>\n" \
" </method>\n" \
- " <method name=\"ListSessions\">\n" \
- " <arg name=\"users\" type=\"a(sussso)\" direction=\"out\"/>\n" \
+ " <method name=\"ListSeats\">\n" \
+ " <arg name=\"seats\" type=\"a(so)\" direction=\"out\"/>\n" \
" </method>\n" \
" <method name=\"CreateSession\">\n" \
" <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
" <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
" </method>\n" \
+ " <method name=\"ActivateSession\">\n" \
+ " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <method name=\"TerminateSession\">\n" \
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n" \
" <method name=\"TerminateUser\">\n" \
- " <arg name=\"uid\" type=\"t\" direction=\"in\"/>\n" \
+ " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
" </method>\n" \
" <method name=\"TerminateSeat\">\n" \
" <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
" <property name=\"KillOnlyUsers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"KillExcludeUsers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"KillUserProcesses\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
" </interface>\n"
#define INTROSPECTION_BEGIN \
BUS_GENERIC_INTERFACES_LIST \
"org.freedesktop.login1.Manager\0"
+static int bus_manager_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
+ Manager *m = data;
+ bool b;
+
+ assert(i);
+ assert(property);
+ assert(m);
+
+ b = manager_get_idle_hint(m, NULL);
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bus_manager_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
+ Manager *m = data;
+ dual_timestamp t;
+ uint64_t u;
+
+ assert(i);
+ assert(property);
+ assert(m);
+
+ manager_get_idle_hint(m, &t);
+ u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
+ return -ENOMEM;
+
+ return 0;
+}
+
static DBusHandlerResult manager_message_handler(
DBusConnection *connection,
DBusMessage *message,
Manager *m = userdata;
const BusProperty properties[] = {
- { "org.freedesktop.login1.Manager", "ControlGroupHierarchy", bus_property_append_string, "s", m->cgroup_path },
- { "org.freedesktop.login1.Manager", "Controllers", bus_property_append_strv, "as", m->controllers },
- { "org.freedesktop.login1.Manager", "ResetControllers", bus_property_append_strv, "as", m->reset_controllers },
- { "org.freedesktop.login1.Manager", "NAutoVTs", bus_property_append_unsigned, "u", &m->n_autovts },
- { "org.freedesktop.login1.Manager", "KillOnlyUsers", bus_property_append_strv, "as", m->kill_only_users },
- { "org.freedesktop.login1.Manager", "KillExcludeUsers", bus_property_append_strv, "as", m->kill_exclude_users },
- { "org.freedesktop.login1.Manager", "KillUserProcesses", bus_property_append_bool, "b", &m->kill_user_processes },
+ { "org.freedesktop.login1.Manager", "ControlGroupHierarchy", bus_property_append_string, "s", m->cgroup_path },
+ { "org.freedesktop.login1.Manager", "Controllers", bus_property_append_strv, "as", m->controllers },
+ { "org.freedesktop.login1.Manager", "ResetControllers", bus_property_append_strv, "as", m->reset_controllers },
+ { "org.freedesktop.login1.Manager", "NAutoVTs", bus_property_append_unsigned, "u", &m->n_autovts },
+ { "org.freedesktop.login1.Manager", "KillOnlyUsers", bus_property_append_strv, "as", m->kill_only_users },
+ { "org.freedesktop.login1.Manager", "KillExcludeUsers", bus_property_append_strv, "as", m->kill_exclude_users },
+ { "org.freedesktop.login1.Manager", "KillUserProcesses", bus_property_append_bool, "b", &m->kill_user_processes },
+ { "org.freedesktop.login1.Manager", "IdleHint", bus_manager_append_idle_hint, "b", m },
+ { "org.freedesktop.login1.Manager", "IdleSinceHint", bus_manager_append_idle_hint_since, "t", m },
+ { "org.freedesktop.login1.Manager", "IdleSinceHintMonotonic", bus_manager_append_idle_hint_since, "t", m },
{ NULL, NULL, NULL, NULL, NULL }
};
DBusError error;
DBusMessage *reply = NULL;
+ int r;
assert(connection);
assert(message);
dbus_error_init(&error);
- if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+ if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSession")) {
+ const char *name;
+ char *p;
+ Session *session;
+ bool b;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ session = hashmap_get(m->sessions, name);
+ if (!session)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ p = session_bus_path(session);
+ if (!p)
+ goto oom;
+
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_INVALID);
+ free(p);
+
+ if (!b)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetUser")) {
+ uint32_t uid;
+ char *p;
+ User *user;
+ bool b;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &uid,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+ if (!user)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ p = user_bus_path(user);
+ if (!p)
+ goto oom;
+
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_INVALID);
+ free(p);
+
+ if (!b)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSeat")) {
+ const char *name;
+ char *p;
+ Seat *seat;
+ bool b;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ seat = hashmap_get(m->seats, name);
+ if (!seat)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ p = seat_bus_path(seat);
+ if (!p)
+ goto oom;
+
+ b = dbus_message_append_args(
+ reply,
+ DBUS_TYPE_OBJECT_PATH, &p,
+ DBUS_TYPE_INVALID);
+ free(p);
+
+ if (!b)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSessions")) {
+ char *p;
+ Session *session;
+ Iterator i;
+ DBusMessageIter iter, sub;
+ const char *empty = "";
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "susso", &sub))
+ goto oom;
+
+ HASHMAP_FOREACH(session, m->sessions, i) {
+ DBusMessageIter sub2;
+ uint32_t uid;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
+ goto oom;
+
+ uid = session->user->uid;
+
+ p = session_bus_path(session);
+ if (!p)
+ goto oom;
+
+ if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->user->name) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, session->seat ? (const char**) &session->seat->id : &empty) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
+ free(p);
+ goto oom;
+ }
+
+ free(p);
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListUsers")) {
+ char *p;
+ User *user;
+ Iterator i;
+ DBusMessageIter iter, sub;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "uso", &sub))
+ goto oom;
+
+ HASHMAP_FOREACH(user, m->users, i) {
+ DBusMessageIter sub2;
+ uint32_t uid;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
+ goto oom;
+
+ uid = user->uid;
+
+ p = user_bus_path(user);
+ if (!p)
+ goto oom;
+
+ if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &user->name) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
+ free(p);
+ goto oom;
+ }
+
+ free(p);
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSeats")) {
+ char *p;
+ Seat *seat;
+ Iterator i;
+ DBusMessageIter iter, sub;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "so", &sub))
+ goto oom;
+
+ HASHMAP_FOREACH(seat, m->seats, i) {
+ DBusMessageIter sub2;
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
+ goto oom;
+
+ p = seat_bus_path(seat);
+ if (!p)
+ goto oom;
+
+ if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &seat->id) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
+ free(p);
+ goto oom;
+ }
+
+ free(p);
+
+ if (!dbus_message_iter_close_container(&sub, &sub2))
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSession")) {
+ const char *name;
+ Session *session;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ session = hashmap_get(m->sessions, name);
+ if (!session)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = session_activate(session);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
+ const char *name;
+ Session *session;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ session = hashmap_get(m->sessions, name);
+ if (!session)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = session_stop(session);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateUser")) {
+ uint32_t uid;
+ User *user;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_UINT32, &uid,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
+ if (!user)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = user_stop(user);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSeat")) {
+ const char *name;
+ Seat *seat;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ seat = hashmap_get(m->seats, name);
+ if (!seat)
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+ r = seat_stop_sessions(seat);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
char *introspection = NULL;
FILE *f;
Iterator i;