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