chiark / gitweb /
sd-bus: don't treat KDBUS_ITEM_TIMESTAMP as unknown item
[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                         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                         false,
236                         s->user->uid,
237                         &s->manager->polkit_registry,
238                         error);
239         if (r < 0)
240                 return r;
241         if (r == 0)
242                 return 1; /* Will call us back */
243
244         r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
245         if (r < 0)
246                 return r;
247
248         return sd_bus_reply_method_return(message, NULL);
249 }
250
251 static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
252         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
253         Session *s = userdata;
254         uid_t uid;
255         int r, b;
256
257         assert(message);
258         assert(s);
259
260         r = sd_bus_message_read(message, "b", &b);
261         if (r < 0)
262                 return r;
263
264         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
265         if (r < 0)
266                 return r;
267
268         r = sd_bus_creds_get_euid(creds, &uid);
269         if (r < 0)
270                 return r;
271
272         if (uid != 0 && uid != s->user->uid)
273                 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
274
275         session_set_idle_hint(s, b);
276
277         return sd_bus_reply_method_return(message, NULL);
278 }
279
280 int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
281         Session *s = userdata;
282         const char *swho;
283         int32_t signo;
284         KillWho who;
285         int r;
286
287         assert(message);
288         assert(s);
289
290         r = sd_bus_message_read(message, "si", &swho, &signo);
291         if (r < 0)
292                 return r;
293
294         if (isempty(swho))
295                 who = KILL_ALL;
296         else {
297                 who = kill_who_from_string(swho);
298                 if (who < 0)
299                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
300         }
301
302         if (signo <= 0 || signo >= _NSIG)
303                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
304
305         r = bus_verify_polkit_async(
306                         message,
307                         CAP_KILL,
308                         "org.freedesktop.login1.manage",
309                         false,
310                         s->user->uid,
311                         &s->manager->polkit_registry,
312                         error);
313         if (r < 0)
314                 return r;
315         if (r == 0)
316                 return 1; /* Will call us back */
317
318         r = session_kill(s, who, signo);
319         if (r < 0)
320                 return r;
321
322         return sd_bus_reply_method_return(message, NULL);
323 }
324
325 static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
326         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
327         Session *s = userdata;
328         int r, force;
329         uid_t uid;
330
331         assert(message);
332         assert(s);
333
334         r = sd_bus_message_read(message, "b", &force);
335         if (r < 0)
336                 return r;
337
338         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
339         if (r < 0)
340                 return r;
341
342         r = sd_bus_creds_get_euid(creds, &uid);
343         if (r < 0)
344                 return r;
345
346         if (uid != 0 && (force || uid != s->user->uid))
347                 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
348
349         r = session_set_controller(s, sd_bus_message_get_sender(message), force);
350         if (r < 0)
351                 return r;
352
353         return sd_bus_reply_method_return(message, NULL);
354 }
355
356 static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
357         Session *s = userdata;
358
359         assert(message);
360         assert(s);
361
362         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
363                 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
364
365         session_drop_controller(s);
366
367         return sd_bus_reply_method_return(message, NULL);
368 }
369
370 static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
371         Session *s = userdata;
372         uint32_t major, minor;
373         SessionDevice *sd;
374         dev_t dev;
375         int r;
376
377         assert(message);
378         assert(s);
379
380         r = sd_bus_message_read(message, "uu", &major, &minor);
381         if (r < 0)
382                 return r;
383
384         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
385                 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
386
387         dev = makedev(major, minor);
388         sd = hashmap_get(s->devices, &dev);
389         if (sd)
390                 /* We don't allow retrieving a device multiple times.
391                  * The related ReleaseDevice call is not ref-counted.
392                  * The caller should use dup() if it requires more
393                  * than one fd (it would be functionally
394                  * equivalent). */
395                 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
396
397         r = session_device_new(s, dev, &sd);
398         if (r < 0)
399                 return r;
400
401         r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
402         if (r < 0)
403                 session_device_free(sd);
404
405         return r;
406 }
407
408 static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
409         Session *s = userdata;
410         uint32_t major, minor;
411         SessionDevice *sd;
412         dev_t dev;
413         int r;
414
415         assert(message);
416         assert(s);
417
418         r = sd_bus_message_read(message, "uu", &major, &minor);
419         if (r < 0)
420                 return r;
421
422         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
423                 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
424
425         dev = makedev(major, minor);
426         sd = hashmap_get(s->devices, &dev);
427         if (!sd)
428                 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
429
430         session_device_free(sd);
431         return sd_bus_reply_method_return(message, NULL);
432 }
433
434 static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
435         Session *s = userdata;
436         uint32_t major, minor;
437         SessionDevice *sd;
438         dev_t dev;
439         int r;
440
441         assert(message);
442         assert(s);
443
444         r = sd_bus_message_read(message, "uu", &major, &minor);
445         if (r < 0)
446                 return r;
447
448         if (!session_is_controller(s, sd_bus_message_get_sender(message)))
449                 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
450
451         dev = makedev(major, minor);
452         sd = hashmap_get(s->devices, &dev);
453         if (!sd)
454                 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
455
456         session_device_complete_pause(sd);
457
458         return sd_bus_reply_method_return(message, NULL);
459 }
460
461 const sd_bus_vtable session_vtable[] = {
462         SD_BUS_VTABLE_START(0),
463
464         SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST),
465         SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST),
466         SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
467         BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
468         SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST),
469         SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST),
470         SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST),
471         SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST),
472         SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
473         SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
474         SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
475         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
476         SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
477         SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
478         SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
479         SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
480         SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_CONST),
481         SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST),
482         SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
483         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
484         SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
485         SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
486         SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
487
488         SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
489         SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
490         SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
491         SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
492         SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
493         SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
494         SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
495         SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
496         SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
497         SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED),
498         SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED),
499
500         SD_BUS_SIGNAL("PauseDevice", "uus", 0),
501         SD_BUS_SIGNAL("ResumeDevice", "uuh", 0),
502         SD_BUS_SIGNAL("Lock", NULL, 0),
503         SD_BUS_SIGNAL("Unlock", NULL, 0),
504
505         SD_BUS_VTABLE_END
506 };
507
508 int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
509         Manager *m = userdata;
510         Session *session;
511         int r;
512
513         assert(bus);
514         assert(path);
515         assert(interface);
516         assert(found);
517         assert(m);
518
519         if (streq(path, "/org/freedesktop/login1/session/self")) {
520                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
521                 sd_bus_message *message;
522                 const char *name;
523
524                 message = sd_bus_get_current_message(bus);
525                 if (!message)
526                         return 0;
527
528                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
529                 if (r < 0)
530                         return r;
531
532                 r = sd_bus_creds_get_session(creds, &name);
533                 if (r < 0)
534                         return r;
535
536                 session = hashmap_get(m->sessions, name);
537         } else {
538                 _cleanup_free_ char *e = NULL;
539                 const char *p;
540
541                 p = startswith(path, "/org/freedesktop/login1/session/");
542                 if (!p)
543                         return 0;
544
545                 e = bus_label_unescape(p);
546                 if (!e)
547                         return -ENOMEM;
548
549                 session = hashmap_get(m->sessions, e);
550         }
551
552         if (!session)
553                 return 0;
554
555         *found = session;
556         return 1;
557 }
558
559 char *session_bus_path(Session *s) {
560         _cleanup_free_ char *t = NULL;
561
562         assert(s);
563
564         t = bus_label_escape(s->id);
565         if (!t)
566                 return NULL;
567
568         return strappend("/org/freedesktop/login1/session/", t);
569 }
570
571 int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
572         _cleanup_strv_free_ char **l = NULL;
573         sd_bus_message *message;
574         Manager *m = userdata;
575         Session *session;
576         Iterator i;
577         int r;
578
579         assert(bus);
580         assert(path);
581         assert(nodes);
582
583         HASHMAP_FOREACH(session, m->sessions, i) {
584                 char *p;
585
586                 p = session_bus_path(session);
587                 if (!p)
588                         return -ENOMEM;
589
590                 r = strv_consume(&l, p);
591                 if (r < 0)
592                         return r;
593         }
594
595         message = sd_bus_get_current_message(bus);
596         if (message) {
597                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
598                 const char *name;
599
600                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
601                 if (r >= 0) {
602                         r = sd_bus_creds_get_session(creds, &name);
603                         if (r >= 0) {
604                                 session = hashmap_get(m->sessions, name);
605                                 if (session) {
606                                         r = strv_extend(&l, "/org/freedesktop/login1/session/self");
607                                         if (r < 0)
608                                                 return r;
609                                 }
610                         }
611                 }
612         }
613
614         *nodes = l;
615         l = NULL;
616
617         return 1;
618 }
619
620 int session_send_signal(Session *s, bool new_session) {
621         _cleanup_free_ char *p = NULL;
622
623         assert(s);
624
625         p = session_bus_path(s);
626         if (!p)
627                 return -ENOMEM;
628
629         return sd_bus_emit_signal(
630                         s->manager->bus,
631                         "/org/freedesktop/login1",
632                         "org.freedesktop.login1.Manager",
633                         new_session ? "SessionNew" : "SessionRemoved",
634                         "so", s->id, p);
635 }
636
637 int session_send_changed(Session *s, const char *properties, ...) {
638         _cleanup_free_ char *p = NULL;
639         char **l;
640
641         assert(s);
642
643         if (!s->started)
644                 return 0;
645
646         p = session_bus_path(s);
647         if (!p)
648                 return -ENOMEM;
649
650         l = strv_from_stdarg_alloca(properties);
651
652         return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
653 }
654
655 int session_send_lock(Session *s, bool lock) {
656         _cleanup_free_ char *p = NULL;
657
658         assert(s);
659
660         p = session_bus_path(s);
661         if (!p)
662                 return -ENOMEM;
663
664         return sd_bus_emit_signal(
665                         s->manager->bus,
666                         p,
667                         "org.freedesktop.login1.Session",
668                         lock ? "Lock" : "Unlock",
669                         NULL);
670 }
671
672 int session_send_lock_all(Manager *m, bool lock) {
673         Session *session;
674         Iterator i;
675         int r = 0;
676
677         assert(m);
678
679         HASHMAP_FOREACH(session, m->sessions, i) {
680                 int k;
681
682                 k = session_send_lock(session, lock);
683                 if (k < 0)
684                         r = k;
685         }
686
687         return r;
688 }
689
690 int session_send_create_reply(Session *s, sd_bus_error *error) {
691         _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
692         _cleanup_close_ int fifo_fd = -1;
693         _cleanup_free_ char *p = NULL;
694
695         assert(s);
696
697         /* This is called after the session scope and the user service
698          * were successfully created, and finishes where
699          * bus_manager_create_session() left off. */
700
701         if (!s->create_message)
702                 return 0;
703
704         c = s->create_message;
705         s->create_message = NULL;
706
707         if (error)
708                 return sd_bus_reply_method_error(c, error);
709
710         fifo_fd = session_create_fifo(s);
711         if (fifo_fd < 0)
712                 return fifo_fd;
713
714         /* Update the session and user state files before we notify
715          * the client about the result. */
716         session_save(s);
717         user_save(s->user);
718
719         p = session_bus_path(s);
720         if (!p)
721                 return -ENOMEM;
722
723         log_debug("Sending reply about created session: "
724                   "id=%s object_path=%s uid=%u runtime_path=%s "
725                   "session_fd=%d seat=%s vtnr=%u",
726                   s->id,
727                   p,
728                   (uint32_t) s->user->uid,
729                   s->user->runtime_path,
730                   fifo_fd,
731                   s->seat ? s->seat->id : "",
732                   (uint32_t) s->vtnr);
733
734         return sd_bus_reply_method_return(
735                         c, "soshusub",
736                         s->id,
737                         p,
738                         s->user->runtime_path,
739                         fifo_fd,
740                         (uint32_t) s->user->uid,
741                         s->seat ? s->seat->id : "",
742                         (uint32_t) s->vtnr,
743                         false);
744 }