]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-seat-dbus.c
core: convert PID 1 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"
718db961 28#include "bus-errors.h"
3f49d45a
LP
29#include "logind.h"
30#include "logind-seat.h"
3f49d45a 31
cc377381
LP
32static 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
7fd1b19b 41 _cleanup_free_ char *p = NULL;
cc377381 42 Seat *s = userdata;
3f49d45a 43
cc377381
LP
44 assert(bus);
45 assert(reply);
3f49d45a
LP
46 assert(s);
47
cc377381
LP
48 p = s->active ? session_bus_path(s->active) : strdup("/");
49 if (!p)
3f49d45a
LP
50 return -ENOMEM;
51
cc377381
LP
52 return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
53}
3f49d45a 54
cc377381
LP
55static 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) {
3f49d45a 63
cc377381 64 Seat *s = userdata;
3f49d45a 65
cc377381
LP
66 assert(bus);
67 assert(reply);
68 assert(s);
3f49d45a 69
cc377381 70 return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
3f49d45a
LP
71}
72
cc377381
LP
73static 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
91static 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
109static 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;
3f49d45a 119 Session *session;
cc377381 120 int r;
3f49d45a 121
cc377381
LP
122 assert(bus);
123 assert(reply);
3f49d45a
LP
124 assert(s);
125
cc377381
LP
126 r = sd_bus_message_open_container(reply, 'a', "(so)");
127 if (r < 0)
128 return r;
3f49d45a
LP
129
130 LIST_FOREACH(sessions_by_seat, session, s->sessions) {
7fd1b19b 131 _cleanup_free_ char *p = NULL;
3f49d45a 132
3f49d45a
LP
133 p = session_bus_path(session);
134 if (!p)
135 return -ENOMEM;
136
cc377381
LP
137 r = sd_bus_message_append(reply, "(so)", session->id, p);
138 if (r < 0)
139 return r;
3f49d45a 140
3f49d45a
LP
141 }
142
cc377381
LP
143 r = sd_bus_message_close_container(reply);
144 if (r < 0)
145 return r;
3f49d45a 146
cc377381 147 return 1;
3f49d45a
LP
148}
149
cc377381
LP
150static 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) {
f401e48c 158
cc377381 159 Seat *s = userdata;
f1a8e221 160
cc377381
LP
161 assert(bus);
162 assert(reply);
f1a8e221
LP
163 assert(s);
164
cc377381 165 return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0);
f1a8e221
LP
166}
167
cc377381
LP
168static 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;
f1a8e221 181
cc377381
LP
182 assert(bus);
183 assert(reply);
f1a8e221
LP
184 assert(s);
185
cc377381
LP
186 r = seat_get_idle_hint(s, &t);
187 if (r < 0)
188 return r;
f1a8e221 189
cc377381 190 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
f1a8e221 191
cc377381 192 return sd_bus_message_append(reply, "t", u);
f1a8e221
LP
193}
194
cc377381
LP
195static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata) {
196 Seat *s = userdata;
197 int r;
a185c5aa 198
cc377381
LP
199 assert(bus);
200 assert(message);
a185c5aa
LP
201 assert(s);
202
cc377381
LP
203 r = seat_stop_sessions(s);
204 if (r < 0)
205 return sd_bus_reply_method_errno(bus, message, r, NULL);
a185c5aa 206
cc377381 207 return sd_bus_reply_method_return(bus, message, NULL);
a185c5aa
LP
208}
209
cc377381
LP
210static 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;
a185c5aa 215
cc377381
LP
216 assert(bus);
217 assert(message);
a185c5aa
LP
218 assert(s);
219
cc377381
LP
220 r = sd_bus_message_read(message, "s", &name);
221 if (r < 0)
222 return sd_bus_reply_method_errno(bus, message, r, NULL);
a185c5aa 223
cc377381
LP
224 session = hashmap_get(s->manager->sessions, name);
225 if (!session)
226 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
a185c5aa 227
cc377381
LP
228 if (session->seat != s)
229 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
a185c5aa 230
cc377381
LP
231 r = session_activate(session);
232 if (r < 0)
233 return sd_bus_reply_method_errno(bus, message, r, NULL);
3f49d45a 234
cc377381 235 return sd_bus_reply_method_return(bus, message, NULL);
3f49d45a
LP
236}
237
cc377381
LP
238const sd_bus_vtable seat_vtable[] = {
239 SD_BUS_VTABLE_START(0),
a185c5aa 240
cc377381
LP
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),
3f49d45a 250
cc377381
LP
251 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0),
252 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0),
a185c5aa 253
cc377381
LP
254 SD_BUS_VTABLE_END
255};
a185c5aa 256
cc377381 257int seat_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
cc377381
LP
258 Manager *m = userdata;
259 Seat *seat;
927b1649 260 int r;
a185c5aa 261
cc377381
LP
262 assert(bus);
263 assert(path);
264 assert(interface);
265 assert(found);
266 assert(m);
a185c5aa 267
927b1649
LP
268 if (streq(path, "/org/freedesktop/login1/seat/self")) {
269 sd_bus_message *message;
270 Session *session;
271 pid_t pid;
a185c5aa 272
927b1649
LP
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;
a185c5aa 287
927b1649
LP
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 = bus_path_unescape(p);
298 if (!e)
299 return -ENOMEM;
300
301 seat = hashmap_get(m->seats, e);
302 if (!seat)
303 return 0;
304 }
a185c5aa 305
cc377381
LP
306 *found = seat;
307 return 1;
308}
a185c5aa 309
cc377381
LP
310char *seat_bus_path(Seat *s) {
311 _cleanup_free_ char *t = NULL;
a185c5aa 312
cc377381 313 assert(s);
a185c5aa 314
cc377381
LP
315 t = bus_path_escape(s->id);
316 if (!t)
317 return NULL;
a185c5aa 318
cc377381 319 return strappend("/org/freedesktop/login1/seat/", t);
3f49d45a
LP
320}
321
cc377381
LP
322int seat_node_enumerator(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
323 _cleanup_strv_free_ char **l = NULL;
3f49d45a 324 Manager *m = userdata;
cc377381
LP
325 Seat *seat;
326 Iterator i;
3f49d45a
LP
327 int r;
328
cc377381
LP
329 assert(bus);
330 assert(path);
331 assert(nodes);
3f49d45a 332
cc377381
LP
333 HASHMAP_FOREACH(seat, m->seats, i) {
334 char *p;
3f49d45a 335
cc377381
LP
336 p = seat_bus_path(seat);
337 if (!p)
338 return -ENOMEM;
3f49d45a 339
cc377381
LP
340 r = strv_push(&l, p);
341 if (r < 0) {
342 free(p);
343 return r;
3f49d45a 344 }
3f49d45a
LP
345 }
346
cc377381
LP
347 *nodes = l;
348 l = NULL;
3f49d45a 349
cc377381 350 return 1;
3f49d45a 351}
da119395
LP
352
353int seat_send_signal(Seat *s, bool new_seat) {
ce0fc5f5 354 _cleanup_free_ char *p = NULL;
da119395
LP
355
356 assert(s);
357
da119395
LP
358 p = seat_bus_path(s);
359 if (!p)
4654e558 360 return -ENOMEM;
da119395 361
cc377381
LP
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);
da119395 368}
9418f147 369
cc377381 370int seat_send_changed(Seat *s, const char *properties, ...) {
ce0fc5f5 371 _cleanup_free_ char *p = NULL;
cc377381 372 char **l;
9418f147
LP
373
374 assert(s);
375
ed18b08b
LP
376 if (!s->started)
377 return 0;
378
9418f147
LP
379 p = seat_bus_path(s);
380 if (!p)
381 return -ENOMEM;
382
cc377381 383 l = strv_from_stdarg_alloca(properties);
9418f147 384
cc377381 385 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);
9418f147 386}