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