chiark / gitweb /
Prep v229: Remove remaining emacs settings [4/6] src/login
[elogind.git] / src / login / logind-session-dbus.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2011 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <string.h>
22
23 #include "alloc-util.h"
24 #include "bus-common-errors.h"
25 #include "bus-label.h"
26 #include "bus-util.h"
27 #include "fd-util.h"
28 #include "logind-session-device.h"
29 #include "logind-session.h"
30 #include "logind.h"
31 #include "strv.h"
32 #include "util.h"
33
34 static int property_get_user(
35                 sd_bus *bus,
36                 const char *path,
37                 const char *interface,
38                 const char *property,
39                 sd_bus_message *reply,
40                 void *userdata,
41                 sd_bus_error *error) {
42
43         _cleanup_free_ char *p = NULL;
44         Session *s = userdata;
45
46         assert(bus);
47         assert(reply);
48         assert(s);
49
50         p = user_bus_path(s->user);
51         if (!p)
52                 return -ENOMEM;
53
54         return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->uid, p);
55 }
56
57 static int property_get_name(
58                 sd_bus *bus,
59                 const char *path,
60                 const char *interface,
61                 const char *property,
62                 sd_bus_message *reply,
63                 void *userdata,
64                 sd_bus_error *error) {
65
66         Session *s = userdata;
67
68         assert(bus);
69         assert(reply);
70         assert(s);
71
72         return sd_bus_message_append(reply, "s", s->user->name);
73 }
74
75 static int property_get_seat(
76                 sd_bus *bus,
77                 const char *path,
78                 const char *interface,
79                 const char *property,
80                 sd_bus_message *reply,
81                 void *userdata,
82                 sd_bus_error *error) {
83
84         _cleanup_free_ char *p = NULL;
85         Session *s = userdata;
86
87         assert(bus);
88         assert(reply);
89         assert(s);
90
91         p = s->seat ? seat_bus_path(s->seat) : strdup("/");
92         if (!p)
93                 return -ENOMEM;
94
95         return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p);
96 }
97
98 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
99 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
100
101 static int property_get_active(
102                 sd_bus *bus,
103                 const char *path,
104                 const char *interface,
105                 const char *property,
106                 sd_bus_message *reply,
107                 void *userdata,
108                 sd_bus_error *error) {
109
110         Session *s = userdata;
111
112         assert(bus);
113         assert(reply);
114         assert(s);
115
116         return sd_bus_message_append(reply, "b", session_is_active(s));
117 }
118
119 static int property_get_state(
120                 sd_bus *bus,
121                 const char *path,
122                 const char *interface,
123                 const char *property,
124                 sd_bus_message *reply,
125                 void *userdata,
126                 sd_bus_error *error) {
127
128         Session *s = userdata;
129
130         assert(bus);
131         assert(reply);
132         assert(s);
133
134         return sd_bus_message_append(reply, "s", session_state_to_string(session_get_state(s)));
135 }
136
137 static int property_get_idle_hint(
138                 sd_bus *bus,
139                 const char *path,
140                 const char *interface,
141                 const char *property,
142                 sd_bus_message *reply,
143                 void *userdata,
144                 sd_bus_error *error) {
145
146         Session *s = userdata;
147
148         assert(bus);
149         assert(reply);
150         assert(s);
151
152         return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0);
153 }
154
155 static int property_get_idle_since_hint(
156                 sd_bus *bus,
157                 const char *path,
158                 const char *interface,
159                 const char *property,
160                 sd_bus_message *reply,
161                 void *userdata,
162                 sd_bus_error *error) {
163
164         Session *s = userdata;
165         dual_timestamp t = DUAL_TIMESTAMP_NULL;
166         uint64_t u;
167         int r;
168
169         assert(bus);
170         assert(reply);
171         assert(s);
172
173         r = session_get_idle_hint(s, &t);
174         if (r < 0)
175                 return r;
176
177         u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
178
179         return sd_bus_message_append(reply, "t", u);
180 }
181
182 int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
183         Session *s = userdata;
184         int r;
185
186         assert(message);
187         assert(s);
188
189         r = bus_verify_polkit_async(
190                         message,
191                         CAP_KILL,
192                         "org.freedesktop.login1.manage",
193                         NULL,
194                         false,
195                         s->user->uid,
196                         &s->manager->polkit_registry,
197                         error);
198         if (r < 0)
199                 return r;
200         if (r == 0)
201                 return 1; /* Will call us back */
202
203         r = session_stop(s, true);
204         if (r < 0)
205                 return r;
206
207         return sd_bus_reply_method_return(message, NULL);
208 }
209
210 int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
211         Session *s = userdata;
212         int r;
213
214         assert(message);
215         assert(s);
216
217         r = session_activate(s);
218         if (r < 0)
219                 return r;
220
221         return sd_bus_reply_method_return(message, NULL);
222 }
223
224 int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) {
225         Session *s = userdata;
226         int r;
227
228         assert(message);
229         assert(s);
230
231         r = bus_verify_polkit_async(
232                         message,
233                         CAP_SYS_ADMIN,
234                         "org.freedesktop.login1.lock-sessions",
235                         NULL,
236                         false,
237                         s->user->uid,
238                         &s->manager->polkit_registry,
239                         error);
240         if (r < 0)
241                 return r;
242         if (r == 0)
243                 return 1; /* Will call us back */
244
245         r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
246         if (r < 0)
247                 return r;
248
249         return sd_bus_reply_method_return(message, NULL);
250 }
251
252 static int method_set_idle_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 idle hint");
275
276         session_set_idle_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 (signo <= 0 || signo >= _NSIG)
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);
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, &sd);
400         if (r < 0)
401                 return r;
402
403         r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
404         if (r < 0)
405                 session_device_free(sd);
406
407         return r;
408 }
409
410 static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
411         Session *s = userdata;
412         uint32_t major, minor;
413         SessionDevice *sd;
414         dev_t dev;
415         int r;
416
417         assert(message);
418         assert(s);
419
420         r = sd_bus_message_read(message, "uu", &major, &minor);
421         if (r < 0)
422                 return r;
423
424         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
425                 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
426
427         dev = makedev(major, minor);
428         sd = hashmap_get(s->devices, &dev);
429         if (!sd)
430                 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
431
432         session_device_free(sd);
433         return sd_bus_reply_method_return(message, NULL);
434 }
435
436 static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
437         Session *s = userdata;
438         uint32_t major, minor;
439         SessionDevice *sd;
440         dev_t dev;
441         int r;
442
443         assert(message);
444         assert(s);
445
446         r = sd_bus_message_read(message, "uu", &major, &minor);
447         if (r < 0)
448                 return r;
449
450         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
451                 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
452
453         dev = makedev(major, minor);
454         sd = hashmap_get(s->devices, &dev);
455         if (!sd)
456                 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
457
458         session_device_complete_pause(sd);
459
460         return sd_bus_reply_method_return(message, NULL);
461 }
462
463 const sd_bus_vtable session_vtable[] = {
464         SD_BUS_VTABLE_START(0),
465
466         SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST),
467         SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST),
468         SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
469         BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
470         SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST),
471         SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST),
472         SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST),
473         SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST),
474         SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
475         SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
476         SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
477         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
478         SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
479         SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
480         SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
481         SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
482         SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_CONST),
483         SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST),
484         SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
485         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
486         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
487         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
488         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
489
490         SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
491         SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
492         SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
493         SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
494         SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
495         SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
496         SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
497         SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
498         SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
499         SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED),
500         SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED),
501
502         SD_BUS_SIGNAL("PauseDevice", "uus", 0),
503         SD_BUS_SIGNAL("ResumeDevice", "uuh", 0),
504         SD_BUS_SIGNAL("Lock", NULL, 0),
505         SD_BUS_SIGNAL("Unlock", NULL, 0),
506
507         SD_BUS_VTABLE_END
508 };
509
510 int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
511         Manager *m = userdata;
512         Session *session;
513         int r;
514
515         assert(bus);
516         assert(path);
517         assert(interface);
518         assert(found);
519         assert(m);
520
521         if (streq(path, "/org/freedesktop/login1/session/self")) {
522                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
523                 sd_bus_message *message;
524                 const char *name;
525
526                 message = sd_bus_get_current_message(bus);
527                 if (!message)
528                         return 0;
529
530                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
531                 if (r < 0)
532                         return r;
533
534                 r = sd_bus_creds_get_session(creds, &name);
535                 if (r < 0)
536                         return r;
537
538                 session = hashmap_get(m->sessions, name);
539         } else {
540                 _cleanup_free_ char *e = NULL;
541                 const char *p;
542
543                 p = startswith(path, "/org/freedesktop/login1/session/");
544                 if (!p)
545                         return 0;
546
547                 e = bus_label_unescape(p);
548                 if (!e)
549                         return -ENOMEM;
550
551                 session = hashmap_get(m->sessions, e);
552         }
553
554         if (!session)
555                 return 0;
556
557         *found = session;
558         return 1;
559 }
560
561 char *session_bus_path(Session *s) {
562         _cleanup_free_ char *t = NULL;
563
564         assert(s);
565
566         t = bus_label_escape(s->id);
567         if (!t)
568                 return NULL;
569
570         return strappend("/org/freedesktop/login1/session/", t);
571 }
572
573 int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
574         _cleanup_strv_free_ char **l = NULL;
575         sd_bus_message *message;
576         Manager *m = userdata;
577         Session *session;
578         Iterator i;
579         int r;
580
581         assert(bus);
582         assert(path);
583         assert(nodes);
584
585         HASHMAP_FOREACH(session, m->sessions, i) {
586                 char *p;
587
588                 p = session_bus_path(session);
589                 if (!p)
590                         return -ENOMEM;
591
592                 r = strv_consume(&l, p);
593                 if (r < 0)
594                         return r;
595         }
596
597         message = sd_bus_get_current_message(bus);
598         if (message) {
599                 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
600                 const char *name;
601
602                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
603                 if (r >= 0) {
604                         r = sd_bus_creds_get_session(creds, &name);
605                         if (r >= 0) {
606                                 session = hashmap_get(m->sessions, name);
607                                 if (session) {
608                                         r = strv_extend(&l, "/org/freedesktop/login1/session/self");
609                                         if (r < 0)
610                                                 return r;
611                                 }
612                         }
613                 }
614         }
615
616         *nodes = l;
617         l = NULL;
618
619         return 1;
620 }
621
622 int session_send_signal(Session *s, bool new_session) {
623         _cleanup_free_ char *p = NULL;
624
625         assert(s);
626
627         p = session_bus_path(s);
628         if (!p)
629                 return -ENOMEM;
630
631         return sd_bus_emit_signal(
632                         s->manager->bus,
633                         "/org/freedesktop/login1",
634                         "org.freedesktop.login1.Manager",
635                         new_session ? "SessionNew" : "SessionRemoved",
636                         "so", s->id, p);
637 }
638
639 int session_send_changed(Session *s, const char *properties, ...) {
640         _cleanup_free_ char *p = NULL;
641         char **l;
642
643         assert(s);
644
645         if (!s->started)
646                 return 0;
647
648         p = session_bus_path(s);
649         if (!p)
650                 return -ENOMEM;
651
652         l = strv_from_stdarg_alloca(properties);
653
654         return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
655 }
656
657 int session_send_lock(Session *s, bool lock) {
658         _cleanup_free_ char *p = NULL;
659
660         assert(s);
661
662         p = session_bus_path(s);
663         if (!p)
664                 return -ENOMEM;
665
666         return sd_bus_emit_signal(
667                         s->manager->bus,
668                         p,
669                         "org.freedesktop.login1.Session",
670                         lock ? "Lock" : "Unlock",
671                         NULL);
672 }
673
674 int session_send_lock_all(Manager *m, bool lock) {
675         Session *session;
676         Iterator i;
677         int r = 0;
678
679         assert(m);
680
681         HASHMAP_FOREACH(session, m->sessions, i) {
682                 int k;
683
684                 k = session_send_lock(session, lock);
685                 if (k < 0)
686                         r = k;
687         }
688
689         return r;
690 }
691
692 int session_send_create_reply(Session *s, sd_bus_error *error) {
693         _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
694         _cleanup_close_ int fifo_fd = -1;
695         _cleanup_free_ char *p = NULL;
696
697         assert(s);
698
699         /* This is called after the session scope and the user service
700          * were successfully created, and finishes where
701          * bus_manager_create_session() left off. */
702
703         if (!s->create_message)
704                 return 0;
705
706 #if 0 /// elogind does not support scope and service jobs
707         if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
708                 return 0;
709 #endif // 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 and user state files before we notify
722          * the client about the result. */
723         session_save(s);
724         user_save(s->user);
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 }