chiark / gitweb /
0be2f8abef94791facedd88ef1654c82e57a6321
[elogind.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_bus_creds_unref_ 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_bus_creds_unref_ 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_bus_creds_unref_ 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_bus_creds_unref_ 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_bus_message_unref_ 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 /// elogind does not support scope and service jobs
709 #if 0
710         if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
711                 return 0;
712 #endif // 0
713
714         c = s->create_message;
715         s->create_message = NULL;
716
717         if (error)
718                 return sd_bus_reply_method_error(c, error);
719
720         fifo_fd = session_create_fifo(s);
721         if (fifo_fd < 0)
722                 return fifo_fd;
723
724         /* Update the session and user state files before we notify
725          * the client about the result. */
726         session_save(s);
727         user_save(s->user);
728
729         p = session_bus_path(s);
730         if (!p)
731                 return -ENOMEM;
732
733         log_debug("Sending reply about created session: "
734                   "id=%s object_path=%s uid=%u runtime_path=%s "
735                   "session_fd=%d seat=%s vtnr=%u",
736                   s->id,
737                   p,
738                   (uint32_t) s->user->uid,
739                   s->user->runtime_path,
740                   fifo_fd,
741                   s->seat ? s->seat->id : "",
742                   (uint32_t) s->vtnr);
743
744         return sd_bus_reply_method_return(
745                         c, "soshusub",
746                         s->id,
747                         p,
748                         s->user->runtime_path,
749                         fifo_fd,
750                         (uint32_t) s->user->uid,
751                         s->seat ? s->seat->id : "",
752                         (uint32_t) s->vtnr,
753                         false);
754 }