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