]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-seat-dbus.c
bus: let's simplify things by getting rid of unnecessary bus parameters
[thirdparty/systemd.git] / src / login / logind-seat-dbus.c
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
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.
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
16 Lesser General Public License for more details.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <string.h>
24
25 #include "util.h"
26 #include "bus-util.h"
27 #include "strv.h"
28 #include "bus-errors.h"
29 #include "logind.h"
30 #include "logind-seat.h"
31
32 static int property_get_active_session(
33 sd_bus *bus,
34 const char *path,
35 const char *interface,
36 const char *property,
37 sd_bus_message *reply,
38 sd_bus_error *error,
39 void *userdata) {
40
41 _cleanup_free_ char *p = NULL;
42 Seat *s = userdata;
43
44 assert(bus);
45 assert(reply);
46 assert(s);
47
48 p = s->active ? session_bus_path(s->active) : strdup("/");
49 if (!p)
50 return -ENOMEM;
51
52 return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
53 }
54
55 static int property_get_can_multi_session(
56 sd_bus *bus,
57 const char *path,
58 const char *interface,
59 const char *property,
60 sd_bus_message *reply,
61 sd_bus_error *error,
62 void *userdata) {
63
64 Seat *s = userdata;
65
66 assert(bus);
67 assert(reply);
68 assert(s);
69
70 return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
71 }
72
73 static int property_get_can_tty(
74 sd_bus *bus,
75 const char *path,
76 const char *interface,
77 const char *property,
78 sd_bus_message *reply,
79 sd_bus_error *error,
80 void *userdata) {
81
82 Seat *s = userdata;
83
84 assert(bus);
85 assert(reply);
86 assert(s);
87
88 return sd_bus_message_append(reply, "b", seat_can_tty(s));
89 }
90
91 static int property_get_can_graphical(
92 sd_bus *bus,
93 const char *path,
94 const char *interface,
95 const char *property,
96 sd_bus_message *reply,
97 sd_bus_error *error,
98 void *userdata) {
99
100 Seat *s = userdata;
101
102 assert(bus);
103 assert(reply);
104 assert(s);
105
106 return sd_bus_message_append(reply, "b", seat_can_tty(s));
107 }
108
109 static int property_get_sessions(
110 sd_bus *bus,
111 const char *path,
112 const char *interface,
113 const char *property,
114 sd_bus_message *reply,
115 sd_bus_error *error,
116 void *userdata) {
117
118 Seat *s = userdata;
119 Session *session;
120 int r;
121
122 assert(bus);
123 assert(reply);
124 assert(s);
125
126 r = sd_bus_message_open_container(reply, 'a', "(so)");
127 if (r < 0)
128 return r;
129
130 LIST_FOREACH(sessions_by_seat, session, s->sessions) {
131 _cleanup_free_ char *p = NULL;
132
133 p = session_bus_path(session);
134 if (!p)
135 return -ENOMEM;
136
137 r = sd_bus_message_append(reply, "(so)", session->id, p);
138 if (r < 0)
139 return r;
140
141 }
142
143 r = sd_bus_message_close_container(reply);
144 if (r < 0)
145 return r;
146
147 return 1;
148 }
149
150 static int property_get_idle_hint(
151 sd_bus *bus,
152 const char *path,
153 const char *interface,
154 const char *property,
155 sd_bus_message *reply,
156 sd_bus_error *error,
157 void *userdata) {
158
159 Seat *s = userdata;
160
161 assert(bus);
162 assert(reply);
163 assert(s);
164
165 return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0);
166 }
167
168 static int property_get_idle_since_hint(
169 sd_bus *bus,
170 const char *path,
171 const char *interface,
172 const char *property,
173 sd_bus_message *reply,
174 sd_bus_error *error,
175 void *userdata) {
176
177 Seat *s = userdata;
178 dual_timestamp t;
179 uint64_t u;
180 int r;
181
182 assert(bus);
183 assert(reply);
184 assert(s);
185
186 r = seat_get_idle_hint(s, &t);
187 if (r < 0)
188 return r;
189
190 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
191
192 return sd_bus_message_append(reply, "t", u);
193 }
194
195 static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata) {
196 Seat *s = userdata;
197 int r;
198
199 assert(bus);
200 assert(message);
201 assert(s);
202
203 r = seat_stop_sessions(s);
204 if (r < 0)
205 return sd_bus_reply_method_errno(message, r, NULL);
206
207 return sd_bus_reply_method_return(message, NULL);
208 }
209
210 static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
211 Seat *s = userdata;
212 const char *name;
213 Session *session;
214 int r;
215
216 assert(bus);
217 assert(message);
218 assert(s);
219
220 r = sd_bus_message_read(message, "s", &name);
221 if (r < 0)
222 return sd_bus_reply_method_errno(message, r, NULL);
223
224 session = hashmap_get(s->manager->sessions, name);
225 if (!session)
226 return sd_bus_reply_method_errorf(message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
227
228 if (session->seat != s)
229 return sd_bus_reply_method_errorf(message, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
230
231 r = session_activate(session);
232 if (r < 0)
233 return sd_bus_reply_method_errno(message, r, NULL);
234
235 return sd_bus_reply_method_return(message, NULL);
236 }
237
238 const sd_bus_vtable seat_vtable[] = {
239 SD_BUS_VTABLE_START(0),
240
241 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), 0),
242 SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
243 SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, 0),
244 SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, 0),
245 SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
246 SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
247 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
248 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
249 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
250
251 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0),
252 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0),
253
254 SD_BUS_VTABLE_END
255 };
256
257 int seat_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
258 Manager *m = userdata;
259 Seat *seat;
260 int r;
261
262 assert(bus);
263 assert(path);
264 assert(interface);
265 assert(found);
266 assert(m);
267
268 if (streq(path, "/org/freedesktop/login1/seat/self")) {
269 sd_bus_message *message;
270 Session *session;
271 pid_t pid;
272
273 message = sd_bus_get_current(bus);
274 if (!message)
275 return 0;
276
277 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
278 if (r < 0)
279 return 0;
280
281 r = manager_get_session_by_pid(m, pid, &session);
282 if (r <= 0)
283 return 0;
284
285 if (!session->seat)
286 return 0;
287
288 seat = session->seat;
289 } else {
290 _cleanup_free_ char *e = NULL;
291 const char *p;
292
293 p = startswith(path, "/org/freedesktop/login1/seat/");
294 if (!p)
295 return 0;
296
297 e = sd_bus_label_unescape(p);
298 if (!e)
299 return -ENOMEM;
300
301 seat = hashmap_get(m->seats, e);
302 if (!seat)
303 return 0;
304 }
305
306 *found = seat;
307 return 1;
308 }
309
310 char *seat_bus_path(Seat *s) {
311 _cleanup_free_ char *t = NULL;
312
313 assert(s);
314
315 t = sd_bus_label_escape(s->id);
316 if (!t)
317 return NULL;
318
319 return strappend("/org/freedesktop/login1/seat/", t);
320 }
321
322 int seat_node_enumerator(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
323 _cleanup_strv_free_ char **l = NULL;
324 Manager *m = userdata;
325 Seat *seat;
326 Iterator i;
327 int r;
328
329 assert(bus);
330 assert(path);
331 assert(nodes);
332
333 HASHMAP_FOREACH(seat, m->seats, i) {
334 char *p;
335
336 p = seat_bus_path(seat);
337 if (!p)
338 return -ENOMEM;
339
340 r = strv_push(&l, p);
341 if (r < 0) {
342 free(p);
343 return r;
344 }
345 }
346
347 *nodes = l;
348 l = NULL;
349
350 return 1;
351 }
352
353 int seat_send_signal(Seat *s, bool new_seat) {
354 _cleanup_free_ char *p = NULL;
355
356 assert(s);
357
358 p = seat_bus_path(s);
359 if (!p)
360 return -ENOMEM;
361
362 return sd_bus_emit_signal(
363 s->manager->bus,
364 "/org/freedesktop/login1",
365 "org.freedesktop.login1.Manager",
366 new_seat ? "SeatNew" : "SeatRemoved",
367 "so", s->id, p);
368 }
369
370 int seat_send_changed(Seat *s, const char *properties, ...) {
371 _cleanup_free_ char *p = NULL;
372 char **l;
373
374 assert(s);
375
376 if (!s->started)
377 return 0;
378
379 p = seat_bus_path(s);
380 if (!p)
381 return -ENOMEM;
382
383 l = strv_from_stdarg_alloca(properties);
384
385 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);
386 }