]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-session-dbus.c
networkd-dhcp6: Support ICMPv6 Other information
[thirdparty/systemd.git] / src / login / logind-session-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 "strv.h"
28#include "bus-util.h"
718db961 29#include "bus-errors.h"
a6278b88 30#include "bus-label.h"
cc377381 31
3f49d45a
LP
32#include "logind.h"
33#include "logind-session.h"
118ecf32 34#include "logind-session-device.h"
3f49d45a 35
cc377381
LP
36static int property_get_user(
37 sd_bus *bus,
38 const char *path,
39 const char *interface,
40 const char *property,
41 sd_bus_message *reply,
ebcf1f97
LP
42 void *userdata,
43 sd_bus_error *error) {
cc377381
LP
44
45 _cleanup_free_ char *p = NULL;
46 Session *s = userdata;
47
48 assert(bus);
49 assert(reply);
3f49d45a
LP
50 assert(s);
51
cc377381
LP
52 p = user_bus_path(s->user);
53 if (!p)
3f49d45a
LP
54 return -ENOMEM;
55
cc377381
LP
56 return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->uid, p);
57}
3f49d45a 58
cc377381
LP
59static int property_get_name(
60 sd_bus *bus,
61 const char *path,
62 const char *interface,
63 const char *property,
64 sd_bus_message *reply,
ebcf1f97
LP
65 void *userdata,
66 sd_bus_error *error) {
3f49d45a 67
cc377381 68 Session *s = userdata;
3f49d45a 69
cc377381
LP
70 assert(bus);
71 assert(reply);
72 assert(s);
3f49d45a 73
cc377381 74 return sd_bus_message_append(reply, "s", s->user->name);
3f49d45a
LP
75}
76
cc377381
LP
77static int property_get_seat(
78 sd_bus *bus,
79 const char *path,
80 const char *interface,
81 const char *property,
82 sd_bus_message *reply,
ebcf1f97
LP
83 void *userdata,
84 sd_bus_error *error) {
3f49d45a 85
cc377381
LP
86 _cleanup_free_ char *p = NULL;
87 Session *s = userdata;
3f49d45a 88
cc377381
LP
89 assert(bus);
90 assert(reply);
91 assert(s);
3f49d45a 92
cc377381 93 p = s->seat ? seat_bus_path(s->seat) : strdup("/");
3f49d45a
LP
94 if (!p)
95 return -ENOMEM;
96
cc377381
LP
97 return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p);
98}
3f49d45a 99
cc377381
LP
100static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
101static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
3f49d45a 102
cc377381
LP
103static int property_get_active(
104 sd_bus *bus,
105 const char *path,
106 const char *interface,
107 const char *property,
108 sd_bus_message *reply,
ebcf1f97
LP
109 void *userdata,
110 sd_bus_error *error) {
3f49d45a 111
cc377381 112 Session *s = userdata;
3f49d45a 113
cc377381
LP
114 assert(bus);
115 assert(reply);
3f49d45a
LP
116 assert(s);
117
cc377381 118 return sd_bus_message_append(reply, "b", session_is_active(s));
3f49d45a
LP
119}
120
cc377381
LP
121static int property_get_state(
122 sd_bus *bus,
123 const char *path,
124 const char *interface,
125 const char *property,
126 sd_bus_message *reply,
ebcf1f97
LP
127 void *userdata,
128 sd_bus_error *error) {
a185c5aa 129
cc377381
LP
130 Session *s = userdata;
131
132 assert(bus);
133 assert(reply);
a185c5aa
LP
134 assert(s);
135
cc377381
LP
136 return sd_bus_message_append(reply, "s", session_state_to_string(session_get_state(s)));
137}
138
139static int property_get_idle_hint(
140 sd_bus *bus,
141 const char *path,
142 const char *interface,
143 const char *property,
144 sd_bus_message *reply,
ebcf1f97
LP
145 void *userdata,
146 sd_bus_error *error) {
a185c5aa 147
cc377381
LP
148 Session *s = userdata;
149
150 assert(bus);
151 assert(reply);
152 assert(s);
153
154 return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0);
a185c5aa
LP
155}
156
cc377381
LP
157static int property_get_idle_since_hint(
158 sd_bus *bus,
159 const char *path,
160 const char *interface,
161 const char *property,
162 sd_bus_message *reply,
ebcf1f97
LP
163 void *userdata,
164 sd_bus_error *error) {
cc377381
LP
165
166 Session *s = userdata;
a185c5aa
LP
167 dual_timestamp t;
168 uint64_t u;
ca4f2b6d 169 int r;
a185c5aa 170
cc377381
LP
171 assert(bus);
172 assert(reply);
a185c5aa
LP
173 assert(s);
174
ca4f2b6d
VP
175 r = session_get_idle_hint(s, &t);
176 if (r < 0)
177 return r;
178
a185c5aa
LP
179 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
180
cc377381 181 return sd_bus_message_append(reply, "t", u);
a185c5aa
LP
182}
183
ebcf1f97 184static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
185 Session *s = userdata;
186 int r;
0604381b 187
cc377381
LP
188 assert(bus);
189 assert(message);
0604381b
LP
190 assert(s);
191
9bb69af4 192 r = session_stop(s, true);
cc377381 193 if (r < 0)
ebcf1f97 194 return r;
0604381b 195
df2d202e 196 return sd_bus_reply_method_return(message, NULL);
0604381b
LP
197}
198
ebcf1f97 199static int method_activate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
200 Session *s = userdata;
201 int r;
3f49d45a 202
cc377381
LP
203 assert(bus);
204 assert(message);
205 assert(s);
3f49d45a 206
cc377381
LP
207 r = session_activate(s);
208 if (r < 0)
ebcf1f97 209 return r;
3f49d45a 210
df2d202e 211 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
212}
213
ebcf1f97 214static int method_lock(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
215 Session *s = userdata;
216 int r;
217
218 assert(bus);
219 assert(message);
220 assert(s);
3f49d45a 221
cc377381
LP
222 r = session_send_lock(s, streq(sd_bus_message_get_member(message), "Lock"));
223 if (r < 0)
ebcf1f97 224 return r;
3f49d45a 225
df2d202e 226 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
227}
228
ebcf1f97 229static int method_set_idle_hint(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
5b12334d 230 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
cc377381
LP
231 Session *s = userdata;
232 uid_t uid;
233 int r, b;
d200735e 234
cc377381
LP
235 assert(bus);
236 assert(message);
237 assert(s);
238
239 r = sd_bus_message_read(message, "b", &b);
240 if (r < 0)
ebcf1f97 241 return r;
d200735e 242
5b12334d
LP
243 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
244 if (r < 0)
245 return r;
246
247 r = sd_bus_creds_get_uid(creds, &uid);
cc377381 248 if (r < 0)
ebcf1f97 249 return r;
cc377381
LP
250
251 if (uid != 0 && uid != s->user->uid)
2b233285 252 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
cc377381
LP
253
254 session_set_idle_hint(s, b);
3f49d45a 255
df2d202e 256 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
257}
258
ebcf1f97 259static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
260 Session *s = userdata;
261 const char *swho;
262 int32_t signo;
263 KillWho who;
bef422ae
LP
264 int r;
265
cc377381 266 assert(bus);
3f49d45a 267 assert(message);
cc377381 268 assert(s);
3f49d45a 269
cc377381
LP
270 r = sd_bus_message_read(message, "si", &swho, &signo);
271 if (r < 0)
ebcf1f97 272 return r;
cc377381
LP
273
274 if (isempty(swho))
275 who = KILL_ALL;
276 else {
277 who = kill_who_from_string(swho);
278 if (who < 0)
ebcf1f97 279 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
cc377381 280 }
bef422ae 281
cc377381 282 if (signo <= 0 || signo >= _NSIG)
ebcf1f97 283 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
bef422ae 284
cc377381
LP
285 r = session_kill(s, who, signo);
286 if (r < 0)
ebcf1f97 287 return r;
bef422ae 288
df2d202e 289 return sd_bus_reply_method_return(message, NULL);
cc377381 290}
bef422ae 291
ebcf1f97 292static int method_take_control(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
5b12334d 293 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
cc377381
LP
294 Session *s = userdata;
295 int r, force;
296 uid_t uid;
bef422ae 297
cc377381
LP
298 assert(bus);
299 assert(message);
300 assert(s);
bef422ae 301
cc377381
LP
302 r = sd_bus_message_read(message, "b", &force);
303 if (r < 0)
ebcf1f97 304 return r;
bef422ae 305
5b12334d
LP
306 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_UID, &creds);
307 if (r < 0)
308 return r;
309
310 r = sd_bus_creds_get_uid(creds, &uid);
cc377381 311 if (r < 0)
ebcf1f97 312 return r;
bef422ae 313
cc377381 314 if (uid != 0 && (force || uid != s->user->uid))
ebcf1f97 315 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
bef422ae 316
cc377381
LP
317 r = session_set_controller(s, sd_bus_message_get_sender(message), force);
318 if (r < 0)
ebcf1f97 319 return r;
bef422ae 320
df2d202e 321 return sd_bus_reply_method_return(message, NULL);
cc377381 322}
bef422ae 323
ebcf1f97 324static int method_release_control(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 325 Session *s = userdata;
bef422ae 326
cc377381
LP
327 assert(bus);
328 assert(message);
329 assert(s);
5bc849fd 330
cc377381 331 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 332 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
5bc849fd 333
cc377381 334 session_drop_controller(s);
bef422ae 335
df2d202e 336 return sd_bus_reply_method_return(message, NULL);
cc377381 337}
bef422ae 338
ebcf1f97 339static int method_take_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
340 Session *s = userdata;
341 uint32_t major, minor;
342 SessionDevice *sd;
343 dev_t dev;
344 int r;
de07ab16 345
cc377381
LP
346 assert(bus);
347 assert(message);
348 assert(s);
de07ab16 349
cc377381
LP
350 r = sd_bus_message_read(message, "uu", &major, &minor);
351 if (r < 0)
ebcf1f97 352 return r;
cc377381
LP
353
354 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 355 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
cc377381
LP
356
357 dev = makedev(major, minor);
358 sd = hashmap_get(s->devices, &dev);
359 if (sd)
360 /* We don't allow retrieving a device multiple times.
361 * The related ReleaseDevice call is not ref-counted.
362 * The caller should use dup() if it requires more
363 * than one fd (it would be functionally
364 * equivalent). */
ebcf1f97 365 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
cc377381
LP
366
367 r = session_device_new(s, dev, &sd);
368 if (r < 0)
ebcf1f97 369 return r;
de07ab16 370
df2d202e 371 r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
cc377381
LP
372 if (r < 0)
373 session_device_free(sd);
118ecf32 374
cc377381
LP
375 return r;
376}
118ecf32 377
ebcf1f97 378static int method_release_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
379 Session *s = userdata;
380 uint32_t major, minor;
381 SessionDevice *sd;
382 dev_t dev;
383 int r;
118ecf32 384
cc377381
LP
385 assert(bus);
386 assert(message);
387 assert(s);
118ecf32 388
cc377381
LP
389 r = sd_bus_message_read(message, "uu", &major, &minor);
390 if (r < 0)
ebcf1f97 391 return r;
118ecf32 392
cc377381 393 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 394 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
118ecf32 395
cc377381
LP
396 dev = makedev(major, minor);
397 sd = hashmap_get(s->devices, &dev);
398 if (!sd)
ebcf1f97 399 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
118ecf32 400
cc377381 401 session_device_free(sd);
df2d202e 402 return sd_bus_reply_method_return(message, NULL);
cc377381 403}
118ecf32 404
ebcf1f97 405static int method_pause_device_complete(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
406 Session *s = userdata;
407 uint32_t major, minor;
408 SessionDevice *sd;
409 dev_t dev;
410 int r;
118ecf32 411
cc377381
LP
412 assert(bus);
413 assert(message);
414 assert(s);
bef422ae 415
cc377381
LP
416 r = sd_bus_message_read(message, "uu", &major, &minor);
417 if (r < 0)
ebcf1f97 418 return r;
cc377381
LP
419
420 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 421 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
bef422ae 422
cc377381
LP
423 dev = makedev(major, minor);
424 sd = hashmap_get(s->devices, &dev);
425 if (!sd)
ebcf1f97 426 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
bef422ae 427
cc377381 428 session_device_complete_pause(sd);
bef422ae 429
df2d202e 430 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
431}
432
cc377381
LP
433const sd_bus_vtable session_vtable[] = {
434 SD_BUS_VTABLE_START(0),
435
556089dc
LP
436 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST),
437 SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST),
438 SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
439 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
440 SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST),
441 SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST),
442 SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST),
443 SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST),
444 SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
445 SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
446 SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
447 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
a4cd87e9 448 SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
449 SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
450 SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
451 SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
452 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_CONST),
453 SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST),
cc377381
LP
454 SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
455 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
456 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
457 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
458 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
459
adacb957
LP
460 SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
461 SD_BUS_METHOD("Activate", NULL, NULL, method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
cc377381
LP
462 SD_BUS_METHOD("Lock", NULL, NULL, method_lock, 0),
463 SD_BUS_METHOD("Unlock", NULL, NULL, method_lock, 0),
adacb957
LP
464 SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
465 SD_BUS_METHOD("Kill", "si", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
466 SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
467 SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
468 SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
469 SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED),
470 SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED),
cc377381
LP
471
472 SD_BUS_SIGNAL("PauseDevice", "uus", 0),
473 SD_BUS_SIGNAL("ResumeDevice", "uuh", 0),
474 SD_BUS_SIGNAL("Lock", NULL, 0),
475 SD_BUS_SIGNAL("Unlock", NULL, 0),
476
477 SD_BUS_VTABLE_END
478};
3f49d45a 479
f00c3121 480int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
3f49d45a 481 Manager *m = userdata;
cc377381 482 Session *session;
927b1649 483 int r;
3f49d45a 484
cc377381
LP
485 assert(bus);
486 assert(path);
487 assert(interface);
488 assert(found);
489 assert(m);
3f49d45a 490
927b1649 491 if (streq(path, "/org/freedesktop/login1/session/self")) {
5b12334d 492 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
927b1649
LP
493 sd_bus_message *message;
494 pid_t pid;
3f49d45a 495
19befb2d 496 message = sd_bus_get_current_message(bus);
927b1649
LP
497 if (!message)
498 return 0;
499
5b12334d 500 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
927b1649 501 if (r < 0)
5b12334d
LP
502 return r;
503
504 r = sd_bus_creds_get_pid(creds, &pid);
505 if (r < 0)
506 return r;
927b1649
LP
507
508 r = manager_get_session_by_pid(m, pid, &session);
509 if (r <= 0)
510 return 0;
511 } else {
512 _cleanup_free_ char *e = NULL;
513 const char *p;
3f49d45a 514
927b1649
LP
515 p = startswith(path, "/org/freedesktop/login1/session/");
516 if (!p)
517 return 0;
518
a6278b88 519 e = bus_label_unescape(p);
927b1649
LP
520 if (!e)
521 return -ENOMEM;
522
523 session = hashmap_get(m->sessions, e);
524 if (!session)
525 return 0;
526 }
3f49d45a 527
cc377381
LP
528 *found = session;
529 return 1;
3f49d45a
LP
530}
531
3f49d45a 532char *session_bus_path(Session *s) {
9444b1f2 533 _cleanup_free_ char *t = NULL;
3f49d45a
LP
534
535 assert(s);
536
a6278b88 537 t = bus_label_escape(s->id);
3f49d45a
LP
538 if (!t)
539 return NULL;
540
4654e558 541 return strappend("/org/freedesktop/login1/session/", t);
3f49d45a 542}
da119395 543
f00c3121 544int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
cc377381
LP
545 _cleanup_strv_free_ char **l = NULL;
546 Manager *m = userdata;
547 Session *session;
548 Iterator i;
549 int r;
550
551 assert(bus);
552 assert(path);
553 assert(nodes);
554
555 HASHMAP_FOREACH(session, m->sessions, i) {
556 char *p;
557
558 p = session_bus_path(session);
559 if (!p)
560 return -ENOMEM;
561
6e18964d
ZJS
562 r = strv_consume(&l, p);
563 if (r < 0)
cc377381 564 return r;
cc377381
LP
565 }
566
567 *nodes = l;
568 l = NULL;
569
570 return 1;
571}
572
da119395 573int session_send_signal(Session *s, bool new_session) {
ce0fc5f5 574 _cleanup_free_ char *p = NULL;
da119395
LP
575
576 assert(s);
577
da119395
LP
578 p = session_bus_path(s);
579 if (!p)
4654e558 580 return -ENOMEM;
da119395 581
cc377381
LP
582 return sd_bus_emit_signal(
583 s->manager->bus,
584 "/org/freedesktop/login1",
585 "org.freedesktop.login1.Manager",
586 new_session ? "SessionNew" : "SessionRemoved",
587 "so", s->id, p);
da119395 588}
9418f147 589
cc377381 590int session_send_changed(Session *s, const char *properties, ...) {
ce0fc5f5 591 _cleanup_free_ char *p = NULL;
cc377381 592 char **l;
9418f147
LP
593
594 assert(s);
595
ed18b08b
LP
596 if (!s->started)
597 return 0;
598
9418f147
LP
599 p = session_bus_path(s);
600 if (!p)
601 return -ENOMEM;
602
cc377381 603 l = strv_from_stdarg_alloca(properties);
9418f147 604
cc377381 605 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
9418f147 606}
88e3dc90
LP
607
608int session_send_lock(Session *s, bool lock) {
ce0fc5f5 609 _cleanup_free_ char *p = NULL;
88e3dc90
LP
610
611 assert(s);
612
613 p = session_bus_path(s);
614 if (!p)
615 return -ENOMEM;
616
cc377381
LP
617 return sd_bus_emit_signal(
618 s->manager->bus,
619 p,
620 "org.freedesktop.login1.Session",
621 lock ? "Lock" : "Unlock",
622 NULL);
88e3dc90 623}
7ba64386
LP
624
625int session_send_lock_all(Manager *m, bool lock) {
626 Session *session;
627 Iterator i;
628 int r = 0;
629
630 assert(m);
631
632 HASHMAP_FOREACH(session, m->sessions, i) {
633 int k;
634
635 k = session_send_lock(session, lock);
636 if (k < 0)
637 r = k;
638 }
639
640 return r;
641}
fb6becb4 642
cc377381
LP
643int session_send_create_reply(Session *s, sd_bus_error *error) {
644 _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
645 _cleanup_close_ int fifo_fd = -1;
646 _cleanup_free_ char *p = NULL;
fb6becb4
LP
647
648 assert(s);
649
dd9b67aa
LP
650 /* This is called after the session scope and the user service
651 * were successfully created, and finishes where
652 * bus_manager_create_session() left off. */
cba38758 653
cc377381
LP
654 if (!s->create_message)
655 return 0;
fb6becb4 656
dd9b67aa
LP
657 if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
658 return 0;
659
cc377381
LP
660 c = s->create_message;
661 s->create_message = NULL;
fb6becb4 662
cc377381 663 if (error)
df2d202e 664 return sd_bus_reply_method_error(c, error);
fb6becb4 665
cc377381
LP
666 fifo_fd = session_create_fifo(s);
667 if (fifo_fd < 0)
668 return fifo_fd;
fb6becb4 669
38fdcbed
TA
670 /* Update the session state file before we notify the client
671 * about the result. */
672 session_save(s);
673
cc377381
LP
674 p = session_bus_path(s);
675 if (!p)
676 return -ENOMEM;
fb6becb4 677
5a330cda 678 log_debug("Sending reply about created session: "
236af516
DH
679 "id=%s object_path=%s uid=%u runtime_path=%s "
680 "session_fd=%d seat=%s vtnr=%u",
5a330cda
ZJS
681 s->id,
682 p,
236af516 683 (uint32_t) s->user->uid,
5a330cda
ZJS
684 s->user->runtime_path,
685 fifo_fd,
686 s->seat ? s->seat->id : "",
687 (uint32_t) s->vtnr);
688
cc377381 689 return sd_bus_reply_method_return(
baae0358 690 c, "soshusub",
cc377381
LP
691 s->id,
692 p,
693 s->user->runtime_path,
694 fifo_fd,
baae0358 695 (uint32_t) s->user->uid,
cc377381
LP
696 s->seat ? s->seat->id : "",
697 (uint32_t) s->vtnr,
698 false);
fb6becb4 699}