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