1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "logind-seat.h"
31 static int property_get_active_session(
34 const char *interface,
36 sd_bus_message *reply,
40 _cleanup_free_ char *p = NULL;
47 p = s->active ? session_bus_path(s->active) : strdup("/");
51 return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
54 static int property_get_can_multi_session(
57 const char *interface,
59 sd_bus_message *reply,
69 return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
72 static int property_get_can_tty(
75 const char *interface,
77 sd_bus_message *reply,
87 return sd_bus_message_append(reply, "b", seat_can_tty(s));
90 static int property_get_can_graphical(
93 const char *interface,
95 sd_bus_message *reply,
105 return sd_bus_message_append(reply, "b", seat_can_tty(s));
108 static int property_get_sessions(
111 const char *interface,
112 const char *property,
113 sd_bus_message *reply,
125 r = sd_bus_message_open_container(reply, 'a', "(so)");
129 LIST_FOREACH(sessions_by_seat, session, s->sessions) {
130 _cleanup_free_ char *p = NULL;
132 p = session_bus_path(session);
136 r = sd_bus_message_append(reply, "(so)", session->id, p);
142 r = sd_bus_message_close_container(reply);
149 static int property_get_idle_hint(
152 const char *interface,
153 const char *property,
154 sd_bus_message *reply,
164 return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0);
167 static int property_get_idle_since_hint(
170 const char *interface,
171 const char *property,
172 sd_bus_message *reply,
185 r = seat_get_idle_hint(s, &t);
189 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
191 return sd_bus_message_append(reply, "t", u);
194 static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata) {
202 r = seat_stop_sessions(s);
204 return sd_bus_reply_method_errno(bus, message, r, NULL);
206 return sd_bus_reply_method_return(bus, message, NULL);
209 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
219 r = sd_bus_message_read(message, "s", &name);
221 return sd_bus_reply_method_errno(bus, message, r, NULL);
223 session = hashmap_get(s->manager->sessions, name);
225 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
227 if (session->seat != s)
228 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
230 r = session_activate(session);
232 return sd_bus_reply_method_errno(bus, message, r, NULL);
234 return sd_bus_reply_method_return(bus, message, NULL);
237 const sd_bus_vtable seat_vtable[] = {
238 SD_BUS_VTABLE_START(0),
240 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), 0),
241 SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
242 SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, 0),
243 SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, 0),
244 SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
245 SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
246 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
247 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
248 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
250 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0),
251 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0),
256 int seat_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
257 Manager *m = userdata;
267 if (streq(path, "/org/freedesktop/login1/seat/self")) {
268 sd_bus_message *message;
272 message = sd_bus_get_current(bus);
276 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
280 r = manager_get_session_by_pid(m, pid, &session);
287 seat = session->seat;
289 _cleanup_free_ char *e = NULL;
292 p = startswith(path, "/org/freedesktop/login1/seat/");
296 e = bus_path_unescape(p);
300 seat = hashmap_get(m->seats, e);
309 char *seat_bus_path(Seat *s) {
310 _cleanup_free_ char *t = NULL;
314 t = bus_path_escape(s->id);
318 return strappend("/org/freedesktop/login1/seat/", t);
321 int seat_node_enumerator(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
322 _cleanup_strv_free_ char **l = NULL;
323 Manager *m = userdata;
332 HASHMAP_FOREACH(seat, m->seats, i) {
335 p = seat_bus_path(seat);
339 r = strv_push(&l, p);
352 int seat_send_signal(Seat *s, bool new_seat) {
353 _cleanup_free_ char *p = NULL;
357 p = seat_bus_path(s);
361 return sd_bus_emit_signal(
363 "/org/freedesktop/login1",
364 "org.freedesktop.login1.Manager",
365 new_seat ? "SeatNew" : "SeatRemoved",
369 int seat_send_changed(Seat *s, const char *properties, ...) {
370 _cleanup_free_ char *p = NULL;
378 p = seat_bus_path(s);
382 l = strv_from_stdarg_alloca(properties);
384 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);