]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-session-dbus.c
Merge pull request #197 from dvdhrm/hashmap
[thirdparty/systemd.git] / src / login / logind-session-dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <string.h>
24
25 #include "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 if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
705 return 0;
706
707 c = s->create_message;
708 s->create_message = NULL;
709
710 if (error)
711 return sd_bus_reply_method_error(c, error);
712
713 fifo_fd = session_create_fifo(s);
714 if (fifo_fd < 0)
715 return fifo_fd;
716
717 /* Update the session state file before we notify the client
718 * about the result. */
719 session_save(s);
720
721 p = session_bus_path(s);
722 if (!p)
723 return -ENOMEM;
724
725 log_debug("Sending reply about created session: "
726 "id=%s object_path=%s uid=%u runtime_path=%s "
727 "session_fd=%d seat=%s vtnr=%u",
728 s->id,
729 p,
730 (uint32_t) s->user->uid,
731 s->user->runtime_path,
732 fifo_fd,
733 s->seat ? s->seat->id : "",
734 (uint32_t) s->vtnr);
735
736 return sd_bus_reply_method_return(
737 c, "soshusub",
738 s->id,
739 p,
740 s->user->runtime_path,
741 fifo_fd,
742 (uint32_t) s->user->uid,
743 s->seat ? s->seat->id : "",
744 (uint32_t) s->vtnr,
745 false);
746 }