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