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