]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-seat-dbus.c
logind: port logind to libsystemd-bus
[thirdparty/systemd.git] / src / login / logind-seat-dbus.c
CommitLineData
3f49d45a
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
3f49d45a
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
3f49d45a 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
3f49d45a
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
a185c5aa 23#include <string.h>
3f49d45a 24
cc377381
LP
25#include "util.h"
26#include "bus-util.h"
27#include "strv.h"
3f49d45a
LP
28#include "logind.h"
29#include "logind-seat.h"
3f49d45a 30
cc377381
LP
31static int property_get_active_session(
32 sd_bus *bus,
33 const char *path,
34 const char *interface,
35 const char *property,
36 sd_bus_message *reply,
37 sd_bus_error *error,
38 void *userdata) {
39
7fd1b19b 40 _cleanup_free_ char *p = NULL;
cc377381 41 Seat *s = userdata;
3f49d45a 42
cc377381
LP
43 assert(bus);
44 assert(reply);
3f49d45a
LP
45 assert(s);
46
cc377381
LP
47 p = s->active ? session_bus_path(s->active) : strdup("/");
48 if (!p)
3f49d45a
LP
49 return -ENOMEM;
50
cc377381
LP
51 return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
52}
3f49d45a 53
cc377381
LP
54static int property_get_can_multi_session(
55 sd_bus *bus,
56 const char *path,
57 const char *interface,
58 const char *property,
59 sd_bus_message *reply,
60 sd_bus_error *error,
61 void *userdata) {
3f49d45a 62
cc377381 63 Seat *s = userdata;
3f49d45a 64
cc377381
LP
65 assert(bus);
66 assert(reply);
67 assert(s);
3f49d45a 68
cc377381 69 return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
3f49d45a
LP
70}
71
cc377381
LP
72static int property_get_can_tty(
73 sd_bus *bus,
74 const char *path,
75 const char *interface,
76 const char *property,
77 sd_bus_message *reply,
78 sd_bus_error *error,
79 void *userdata) {
80
81 Seat *s = userdata;
82
83 assert(bus);
84 assert(reply);
85 assert(s);
86
87 return sd_bus_message_append(reply, "b", seat_can_tty(s));
88}
89
90static int property_get_can_graphical(
91 sd_bus *bus,
92 const char *path,
93 const char *interface,
94 const char *property,
95 sd_bus_message *reply,
96 sd_bus_error *error,
97 void *userdata) {
98
99 Seat *s = userdata;
100
101 assert(bus);
102 assert(reply);
103 assert(s);
104
105 return sd_bus_message_append(reply, "b", seat_can_tty(s));
106}
107
108static int property_get_sessions(
109 sd_bus *bus,
110 const char *path,
111 const char *interface,
112 const char *property,
113 sd_bus_message *reply,
114 sd_bus_error *error,
115 void *userdata) {
116
117 Seat *s = userdata;
3f49d45a 118 Session *session;
cc377381 119 int r;
3f49d45a 120
cc377381
LP
121 assert(bus);
122 assert(reply);
3f49d45a
LP
123 assert(s);
124
cc377381
LP
125 r = sd_bus_message_open_container(reply, 'a', "(so)");
126 if (r < 0)
127 return r;
3f49d45a
LP
128
129 LIST_FOREACH(sessions_by_seat, session, s->sessions) {
7fd1b19b 130 _cleanup_free_ char *p = NULL;
3f49d45a 131
3f49d45a
LP
132 p = session_bus_path(session);
133 if (!p)
134 return -ENOMEM;
135
cc377381
LP
136 r = sd_bus_message_append(reply, "(so)", session->id, p);
137 if (r < 0)
138 return r;
3f49d45a 139
3f49d45a
LP
140 }
141
cc377381
LP
142 r = sd_bus_message_close_container(reply);
143 if (r < 0)
144 return r;
3f49d45a 145
cc377381 146 return 1;
3f49d45a
LP
147}
148
cc377381
LP
149static int property_get_idle_hint(
150 sd_bus *bus,
151 const char *path,
152 const char *interface,
153 const char *property,
154 sd_bus_message *reply,
155 sd_bus_error *error,
156 void *userdata) {
f401e48c 157
cc377381 158 Seat *s = userdata;
f1a8e221 159
cc377381
LP
160 assert(bus);
161 assert(reply);
f1a8e221
LP
162 assert(s);
163
cc377381 164 return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0);
f1a8e221
LP
165}
166
cc377381
LP
167static int property_get_idle_since_hint(
168 sd_bus *bus,
169 const char *path,
170 const char *interface,
171 const char *property,
172 sd_bus_message *reply,
173 sd_bus_error *error,
174 void *userdata) {
175
176 Seat *s = userdata;
177 dual_timestamp t;
178 uint64_t u;
179 int r;
f1a8e221 180
cc377381
LP
181 assert(bus);
182 assert(reply);
f1a8e221
LP
183 assert(s);
184
cc377381
LP
185 r = seat_get_idle_hint(s, &t);
186 if (r < 0)
187 return r;
f1a8e221 188
cc377381 189 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
f1a8e221 190
cc377381 191 return sd_bus_message_append(reply, "t", u);
f1a8e221
LP
192}
193
cc377381
LP
194static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata) {
195 Seat *s = userdata;
196 int r;
a185c5aa 197
cc377381
LP
198 assert(bus);
199 assert(message);
a185c5aa
LP
200 assert(s);
201
cc377381
LP
202 r = seat_stop_sessions(s);
203 if (r < 0)
204 return sd_bus_reply_method_errno(bus, message, r, NULL);
a185c5aa 205
cc377381 206 return sd_bus_reply_method_return(bus, message, NULL);
a185c5aa
LP
207}
208
cc377381
LP
209static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
210 Seat *s = userdata;
211 const char *name;
212 Session *session;
213 int r;
a185c5aa 214
cc377381
LP
215 assert(bus);
216 assert(message);
a185c5aa
LP
217 assert(s);
218
cc377381
LP
219 r = sd_bus_message_read(message, "s", &name);
220 if (r < 0)
221 return sd_bus_reply_method_errno(bus, message, r, NULL);
a185c5aa 222
cc377381
LP
223 session = hashmap_get(s->manager->sessions, name);
224 if (!session)
225 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
a185c5aa 226
cc377381
LP
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);
a185c5aa 229
cc377381
LP
230 r = session_activate(session);
231 if (r < 0)
232 return sd_bus_reply_method_errno(bus, message, r, NULL);
3f49d45a 233
cc377381 234 return sd_bus_reply_method_return(bus, message, NULL);
3f49d45a
LP
235}
236
cc377381
LP
237const sd_bus_vtable seat_vtable[] = {
238 SD_BUS_VTABLE_START(0),
a185c5aa 239
cc377381
LP
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),
3f49d45a 249
cc377381
LP
250 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0),
251 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0),
a185c5aa 252
cc377381
LP
253 SD_BUS_VTABLE_END
254};
a185c5aa 255
cc377381
LP
256int seat_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
257 _cleanup_free_ char *e = NULL;
258 Manager *m = userdata;
259 Seat *seat;
260 const char *p;
a185c5aa 261
cc377381
LP
262 assert(bus);
263 assert(path);
264 assert(interface);
265 assert(found);
266 assert(m);
a185c5aa 267
cc377381
LP
268 p = startswith(path, "/org/freedesktop/login1/seat/");
269 if (!p)
270 return 0;
a185c5aa 271
cc377381
LP
272 e = bus_path_unescape(p);
273 if (!e)
274 return -ENOMEM;
a185c5aa 275
cc377381
LP
276 seat = hashmap_get(m->seats, e);
277 if (!seat)
278 return 0;
a185c5aa 279
cc377381
LP
280 *found = seat;
281 return 1;
282}
a185c5aa 283
cc377381
LP
284char *seat_bus_path(Seat *s) {
285 _cleanup_free_ char *t = NULL;
a185c5aa 286
cc377381 287 assert(s);
a185c5aa 288
cc377381
LP
289 t = bus_path_escape(s->id);
290 if (!t)
291 return NULL;
a185c5aa 292
cc377381 293 return strappend("/org/freedesktop/login1/seat/", t);
3f49d45a
LP
294}
295
cc377381
LP
296int seat_node_enumerator(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
297 _cleanup_strv_free_ char **l = NULL;
3f49d45a 298 Manager *m = userdata;
cc377381
LP
299 Seat *seat;
300 Iterator i;
3f49d45a
LP
301 int r;
302
cc377381
LP
303 assert(bus);
304 assert(path);
305 assert(nodes);
3f49d45a 306
cc377381
LP
307 HASHMAP_FOREACH(seat, m->seats, i) {
308 char *p;
3f49d45a 309
cc377381
LP
310 p = seat_bus_path(seat);
311 if (!p)
312 return -ENOMEM;
3f49d45a 313
cc377381
LP
314 r = strv_push(&l, p);
315 if (r < 0) {
316 free(p);
317 return r;
3f49d45a 318 }
3f49d45a
LP
319 }
320
cc377381
LP
321 *nodes = l;
322 l = NULL;
3f49d45a 323
cc377381 324 return 1;
3f49d45a 325}
da119395
LP
326
327int seat_send_signal(Seat *s, bool new_seat) {
ce0fc5f5 328 _cleanup_free_ char *p = NULL;
da119395
LP
329
330 assert(s);
331
da119395
LP
332 p = seat_bus_path(s);
333 if (!p)
4654e558 334 return -ENOMEM;
da119395 335
cc377381
LP
336 return sd_bus_emit_signal(
337 s->manager->bus,
338 "/org/freedesktop/login1",
339 "org.freedesktop.login1.Manager",
340 new_seat ? "SeatNew" : "SeatRemoved",
341 "so", s->id, p);
da119395 342}
9418f147 343
cc377381 344int seat_send_changed(Seat *s, const char *properties, ...) {
ce0fc5f5 345 _cleanup_free_ char *p = NULL;
cc377381 346 char **l;
9418f147
LP
347
348 assert(s);
349
ed18b08b
LP
350 if (!s->started)
351 return 0;
352
9418f147
LP
353 p = seat_bus_path(s);
354 if (!p)
355 return -ENOMEM;
356
cc377381 357 l = strv_from_stdarg_alloca(properties);
9418f147 358
cc377381 359 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);
9418f147 360}