]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-seat-dbus.c
bus: add new sd_bus_creds object to encapsulate process credentials
[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,
ebcf1f97
LP
38 void *userdata,
39 sd_bus_error *error) {
cc377381 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,
ebcf1f97
LP
61 void *userdata,
62 sd_bus_error *error) {
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,
ebcf1f97
LP
79 void *userdata,
80 sd_bus_error *error) {
cc377381
LP
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,
ebcf1f97
LP
97 void *userdata,
98 sd_bus_error *error) {
cc377381
LP
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,
ebcf1f97
LP
115 void *userdata,
116 sd_bus_error *error) {
cc377381
LP
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,
ebcf1f97
LP
156 void *userdata,
157 sd_bus_error *error) {
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,
ebcf1f97
LP
174 void *userdata,
175 sd_bus_error *error) {
cc377381
LP
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
ebcf1f97 195static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
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)
ebcf1f97 205 return r;
a185c5aa 206
df2d202e 207 return sd_bus_reply_method_return(message, NULL);
a185c5aa
LP
208}
209
ebcf1f97 210static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
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)
ebcf1f97 222 return r;
a185c5aa 223
cc377381
LP
224 session = hashmap_get(s->manager->sessions, name);
225 if (!session)
ebcf1f97 226 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
a185c5aa 227
cc377381 228 if (session->seat != s)
ebcf1f97 229 return sd_bus_error_setf(error, 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)
ebcf1f97 233 return r;
3f49d45a 234
df2d202e 235 return sd_bus_reply_method_return(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
f00c3121 257int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
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 268 if (streq(path, "/org/freedesktop/login1/seat/self")) {
5b12334d 269 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
927b1649
LP
270 sd_bus_message *message;
271 Session *session;
272 pid_t pid;
a185c5aa 273
927b1649
LP
274 message = sd_bus_get_current(bus);
275 if (!message)
276 return 0;
277
5b12334d 278 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
927b1649 279 if (r < 0)
5b12334d
LP
280 return r;
281
282 r = sd_bus_creds_get_pid(creds, &pid);
283 if (r < 0)
284 return r;
927b1649
LP
285
286 r = manager_get_session_by_pid(m, pid, &session);
287 if (r <= 0)
288 return 0;
289
290 if (!session->seat)
291 return 0;
a185c5aa 292
927b1649
LP
293 seat = session->seat;
294 } else {
295 _cleanup_free_ char *e = NULL;
296 const char *p;
297
298 p = startswith(path, "/org/freedesktop/login1/seat/");
299 if (!p)
300 return 0;
301
28383ba1 302 e = sd_bus_label_unescape(p);
927b1649
LP
303 if (!e)
304 return -ENOMEM;
305
306 seat = hashmap_get(m->seats, e);
307 if (!seat)
308 return 0;
309 }
a185c5aa 310
cc377381
LP
311 *found = seat;
312 return 1;
313}
a185c5aa 314
cc377381
LP
315char *seat_bus_path(Seat *s) {
316 _cleanup_free_ char *t = NULL;
a185c5aa 317
cc377381 318 assert(s);
a185c5aa 319
28383ba1 320 t = sd_bus_label_escape(s->id);
cc377381
LP
321 if (!t)
322 return NULL;
a185c5aa 323
cc377381 324 return strappend("/org/freedesktop/login1/seat/", t);
3f49d45a
LP
325}
326
f00c3121 327int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
cc377381 328 _cleanup_strv_free_ char **l = NULL;
3f49d45a 329 Manager *m = userdata;
cc377381
LP
330 Seat *seat;
331 Iterator i;
3f49d45a
LP
332 int r;
333
cc377381
LP
334 assert(bus);
335 assert(path);
336 assert(nodes);
3f49d45a 337
cc377381
LP
338 HASHMAP_FOREACH(seat, m->seats, i) {
339 char *p;
3f49d45a 340
cc377381
LP
341 p = seat_bus_path(seat);
342 if (!p)
343 return -ENOMEM;
3f49d45a 344
cc377381
LP
345 r = strv_push(&l, p);
346 if (r < 0) {
347 free(p);
348 return r;
3f49d45a 349 }
3f49d45a
LP
350 }
351
cc377381
LP
352 *nodes = l;
353 l = NULL;
3f49d45a 354
cc377381 355 return 1;
3f49d45a 356}
da119395
LP
357
358int seat_send_signal(Seat *s, bool new_seat) {
ce0fc5f5 359 _cleanup_free_ char *p = NULL;
da119395
LP
360
361 assert(s);
362
da119395
LP
363 p = seat_bus_path(s);
364 if (!p)
4654e558 365 return -ENOMEM;
da119395 366
cc377381
LP
367 return sd_bus_emit_signal(
368 s->manager->bus,
369 "/org/freedesktop/login1",
370 "org.freedesktop.login1.Manager",
371 new_seat ? "SeatNew" : "SeatRemoved",
372 "so", s->id, p);
da119395 373}
9418f147 374
cc377381 375int seat_send_changed(Seat *s, const char *properties, ...) {
ce0fc5f5 376 _cleanup_free_ char *p = NULL;
cc377381 377 char **l;
9418f147
LP
378
379 assert(s);
380
ed18b08b
LP
381 if (!s->started)
382 return 0;
383
9418f147
LP
384 p = seat_bus_path(s);
385 if (!p)
386 return -ENOMEM;
387
cc377381 388 l = strv_from_stdarg_alloca(properties);
9418f147 389
cc377381 390 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l);
9418f147 391}