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