]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/login/logind-dbus.c
shared/utmp-wtmp: add parameter for origin tty and callback userdata
[thirdparty/systemd.git] / src / login / logind-dbus.c
... / ...
CommitLineData
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#include <unistd.h>
25#include <pwd.h>
26
27#include "sd-messages.h"
28#include "strv.h"
29#include "mkdir.h"
30#include "path-util.h"
31#include "special.h"
32#include "sleep-config.h"
33#include "fileio-label.h"
34#include "unit-name.h"
35#include "audit.h"
36#include "bus-util.h"
37#include "bus-error.h"
38#include "bus-common-errors.h"
39#include "udev-util.h"
40#include "selinux-util.h"
41#include "efivars.h"
42#include "logind.h"
43#include "formats-util.h"
44#include "process-util.h"
45#include "terminal-util.h"
46
47int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
48 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
49 Session *session;
50 int r;
51
52 assert(m);
53 assert(message);
54 assert(ret);
55
56 if (isempty(name)) {
57 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
58 if (r < 0)
59 return r;
60
61 r = sd_bus_creds_get_session(creds, &name);
62 if (r < 0)
63 return r;
64 }
65
66 session = hashmap_get(m->sessions, name);
67 if (!session)
68 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
69
70 *ret = session;
71 return 0;
72}
73
74int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
75 User *user;
76 int r;
77
78 assert(m);
79 assert(message);
80 assert(ret);
81
82 if (uid == UID_INVALID) {
83 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
84
85 /* Note that we get the owner UID of the session, not the actual client UID here! */
86 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
87 if (r < 0)
88 return r;
89
90 r = sd_bus_creds_get_owner_uid(creds, &uid);
91 if (r < 0)
92 return r;
93 }
94
95 user = hashmap_get(m->users, UID_TO_PTR(uid));
96 if (!user)
97 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
98
99 *ret = user;
100 return 0;
101}
102
103int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
104 Seat *seat;
105 int r;
106
107 assert(m);
108 assert(message);
109 assert(ret);
110
111 if (isempty(name)) {
112 Session *session;
113
114 r = manager_get_session_from_creds(m, message, NULL, error, &session);
115 if (r < 0)
116 return r;
117
118 seat = session->seat;
119
120 if (!seat)
121 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
122 } else {
123 seat = hashmap_get(m->seats, name);
124 if (!seat)
125 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
126 }
127
128 *ret = seat;
129 return 0;
130}
131
132static int property_get_idle_hint(
133 sd_bus *bus,
134 const char *path,
135 const char *interface,
136 const char *property,
137 sd_bus_message *reply,
138 void *userdata,
139 sd_bus_error *error) {
140
141 Manager *m = userdata;
142
143 assert(bus);
144 assert(reply);
145 assert(m);
146
147 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
148}
149
150static int property_get_idle_since_hint(
151 sd_bus *bus,
152 const char *path,
153 const char *interface,
154 const char *property,
155 sd_bus_message *reply,
156 void *userdata,
157 sd_bus_error *error) {
158
159 Manager *m = userdata;
160 dual_timestamp t;
161
162 assert(bus);
163 assert(reply);
164 assert(m);
165
166 manager_get_idle_hint(m, &t);
167
168 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
169}
170
171static int property_get_inhibited(
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 Manager *m = userdata;
181 InhibitWhat w;
182
183 assert(bus);
184 assert(reply);
185 assert(m);
186
187 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
188
189 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
190}
191
192static int property_get_preparing(
193 sd_bus *bus,
194 const char *path,
195 const char *interface,
196 const char *property,
197 sd_bus_message *reply,
198 void *userdata,
199 sd_bus_error *error) {
200
201 Manager *m = userdata;
202 bool b;
203
204 assert(bus);
205 assert(reply);
206 assert(m);
207
208 if (streq(property, "PreparingForShutdown"))
209 b = !!(m->action_what & INHIBIT_SHUTDOWN);
210 else
211 b = !!(m->action_what & INHIBIT_SLEEP);
212
213 return sd_bus_message_append(reply, "b", b);
214}
215
216static int property_get_scheduled_shutdown(
217 sd_bus *bus,
218 const char *path,
219 const char *interface,
220 const char *property,
221 sd_bus_message *reply,
222 void *userdata,
223 sd_bus_error *error) {
224
225 Manager *m = userdata;
226 int r;
227
228 assert(bus);
229 assert(reply);
230 assert(m);
231
232 r = sd_bus_message_open_container(reply, 'r', "st");
233 if (r < 0)
234 return r;
235
236 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
237 if (r < 0)
238 return r;
239
240 return sd_bus_message_close_container(reply);
241}
242
243static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
244
245static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
246 _cleanup_free_ char *p = NULL;
247 Manager *m = userdata;
248 const char *name;
249 Session *session;
250 int r;
251
252 assert(bus);
253 assert(message);
254 assert(m);
255
256 r = sd_bus_message_read(message, "s", &name);
257 if (r < 0)
258 return r;
259
260 r = manager_get_session_from_creds(m, message, name, error, &session);
261 if (r < 0)
262 return r;
263
264 p = session_bus_path(session);
265 if (!p)
266 return -ENOMEM;
267
268 return sd_bus_reply_method_return(message, "o", p);
269}
270
271static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
272 _cleanup_free_ char *p = NULL;
273 Session *session = NULL;
274 Manager *m = userdata;
275 pid_t pid;
276 int r;
277
278 assert(bus);
279 assert(message);
280 assert(m);
281
282 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
283
284 r = sd_bus_message_read(message, "u", &pid);
285 if (r < 0)
286 return r;
287
288 if (pid <= 0) {
289 r = manager_get_session_from_creds(m, message, NULL, error, &session);
290 if (r < 0)
291 return r;
292 } else {
293 r = manager_get_session_by_pid(m, pid, &session);
294 if (r < 0)
295 return r;
296
297 if (!session)
298 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
299 }
300
301 p = session_bus_path(session);
302 if (!p)
303 return -ENOMEM;
304
305 return sd_bus_reply_method_return(message, "o", p);
306}
307
308static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
309 _cleanup_free_ char *p = NULL;
310 Manager *m = userdata;
311 uint32_t uid;
312 User *user;
313 int r;
314
315 assert(bus);
316 assert(message);
317 assert(m);
318
319 r = sd_bus_message_read(message, "u", &uid);
320 if (r < 0)
321 return r;
322
323 r = manager_get_user_from_creds(m, message, uid, error, &user);
324 if (r < 0)
325 return r;
326
327 p = user_bus_path(user);
328 if (!p)
329 return -ENOMEM;
330
331 return sd_bus_reply_method_return(message, "o", p);
332}
333
334static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
335 _cleanup_free_ char *p = NULL;
336 Manager *m = userdata;
337 User *user = NULL;
338 pid_t pid;
339 int r;
340
341 assert(bus);
342 assert(message);
343 assert(m);
344
345 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
346
347 r = sd_bus_message_read(message, "u", &pid);
348 if (r < 0)
349 return r;
350
351 if (pid <= 0) {
352 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
353 if (r < 0)
354 return r;
355 } else {
356 r = manager_get_user_by_pid(m, pid, &user);
357 if (r < 0)
358 return r;
359 if (!user)
360 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
361 }
362
363 p = user_bus_path(user);
364 if (!p)
365 return -ENOMEM;
366
367 return sd_bus_reply_method_return(message, "o", p);
368}
369
370static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
371 _cleanup_free_ char *p = NULL;
372 Manager *m = userdata;
373 const char *name;
374 Seat *seat;
375 int r;
376
377 assert(bus);
378 assert(message);
379 assert(m);
380
381 r = sd_bus_message_read(message, "s", &name);
382 if (r < 0)
383 return r;
384
385 r = manager_get_seat_from_creds(m, message, name, error, &seat);
386 if (r < 0)
387 return r;
388
389 p = seat_bus_path(seat);
390 if (!p)
391 return -ENOMEM;
392
393 return sd_bus_reply_method_return(message, "o", p);
394}
395
396static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
397 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
398 Manager *m = userdata;
399 Session *session;
400 Iterator i;
401 int r;
402
403 assert(bus);
404 assert(message);
405 assert(m);
406
407 r = sd_bus_message_new_method_return(message, &reply);
408 if (r < 0)
409 return r;
410
411 r = sd_bus_message_open_container(reply, 'a', "(susso)");
412 if (r < 0)
413 return r;
414
415 HASHMAP_FOREACH(session, m->sessions, i) {
416 _cleanup_free_ char *p = NULL;
417
418 p = session_bus_path(session);
419 if (!p)
420 return -ENOMEM;
421
422 r = sd_bus_message_append(reply, "(susso)",
423 session->id,
424 (uint32_t) session->user->uid,
425 session->user->name,
426 session->seat ? session->seat->id : "",
427 p);
428 if (r < 0)
429 return r;
430 }
431
432 r = sd_bus_message_close_container(reply);
433 if (r < 0)
434 return r;
435
436 return sd_bus_send(bus, reply, NULL);
437}
438
439static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
440 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
441 Manager *m = userdata;
442 User *user;
443 Iterator i;
444 int r;
445
446 assert(bus);
447 assert(message);
448 assert(m);
449
450 r = sd_bus_message_new_method_return(message, &reply);
451 if (r < 0)
452 return r;
453
454 r = sd_bus_message_open_container(reply, 'a', "(uso)");
455 if (r < 0)
456 return r;
457
458 HASHMAP_FOREACH(user, m->users, i) {
459 _cleanup_free_ char *p = NULL;
460
461 p = user_bus_path(user);
462 if (!p)
463 return -ENOMEM;
464
465 r = sd_bus_message_append(reply, "(uso)",
466 (uint32_t) user->uid,
467 user->name,
468 p);
469 if (r < 0)
470 return r;
471 }
472
473 r = sd_bus_message_close_container(reply);
474 if (r < 0)
475 return r;
476
477 return sd_bus_send(bus, reply, NULL);
478}
479
480static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
481 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
482 Manager *m = userdata;
483 Seat *seat;
484 Iterator i;
485 int r;
486
487 assert(bus);
488 assert(message);
489 assert(m);
490
491 r = sd_bus_message_new_method_return(message, &reply);
492 if (r < 0)
493 return r;
494
495 r = sd_bus_message_open_container(reply, 'a', "(so)");
496 if (r < 0)
497 return r;
498
499 HASHMAP_FOREACH(seat, m->seats, i) {
500 _cleanup_free_ char *p = NULL;
501
502 p = seat_bus_path(seat);
503 if (!p)
504 return -ENOMEM;
505
506 r = sd_bus_message_append(reply, "(so)", seat->id, p);
507 if (r < 0)
508 return r;
509 }
510
511 r = sd_bus_message_close_container(reply);
512 if (r < 0)
513 return r;
514
515 return sd_bus_send(bus, reply, NULL);
516}
517
518static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
519 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
520 Manager *m = userdata;
521 Inhibitor *inhibitor;
522 Iterator i;
523 int r;
524
525 r = sd_bus_message_new_method_return(message, &reply);
526 if (r < 0)
527 return r;
528
529 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
530 if (r < 0)
531 return r;
532
533 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
534
535 r = sd_bus_message_append(reply, "(ssssuu)",
536 strempty(inhibit_what_to_string(inhibitor->what)),
537 strempty(inhibitor->who),
538 strempty(inhibitor->why),
539 strempty(inhibit_mode_to_string(inhibitor->mode)),
540 (uint32_t) inhibitor->uid,
541 (uint32_t) inhibitor->pid);
542 if (r < 0)
543 return r;
544 }
545
546 r = sd_bus_message_close_container(reply);
547 if (r < 0)
548 return r;
549
550 return sd_bus_send(bus, reply, NULL);
551}
552
553static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
554 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
555 uint32_t uid, leader, audit_id = 0;
556 _cleanup_free_ char *id = NULL;
557 Session *session = NULL;
558 Manager *m = userdata;
559 User *user = NULL;
560 Seat *seat = NULL;
561 int remote;
562 uint32_t vtnr = 0;
563 SessionType t;
564 SessionClass c;
565 int r;
566
567 assert(bus);
568 assert(message);
569 assert(m);
570
571 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
572 if (r < 0)
573 return r;
574
575 if (leader == 1)
576 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
577
578 if (isempty(type))
579 t = _SESSION_TYPE_INVALID;
580 else {
581 t = session_type_from_string(type);
582 if (t < 0)
583 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
584 }
585
586 if (isempty(class))
587 c = _SESSION_CLASS_INVALID;
588 else {
589 c = session_class_from_string(class);
590 if (c < 0)
591 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
592 }
593
594 if (isempty(desktop))
595 desktop = NULL;
596 else {
597 if (!string_is_safe(desktop))
598 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
599 }
600
601 if (isempty(cseat))
602 seat = NULL;
603 else {
604 seat = hashmap_get(m->seats, cseat);
605 if (!seat)
606 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
607 }
608
609 if (tty_is_vc(tty)) {
610 int v;
611
612 if (!seat)
613 seat = m->seat0;
614 else if (seat != m->seat0)
615 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
616
617 v = vtnr_from_tty(tty);
618 if (v <= 0)
619 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
620
621 if (!vtnr)
622 vtnr = (uint32_t) v;
623 else if (vtnr != (uint32_t) v)
624 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
625
626 } else if (tty_is_console(tty)) {
627
628 if (!seat)
629 seat = m->seat0;
630 else if (seat != m->seat0)
631 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
632
633 if (vtnr != 0)
634 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
635 }
636
637 if (seat) {
638 if (seat_has_vts(seat)) {
639 if (!vtnr || vtnr > 63)
640 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
641 } else {
642 if (vtnr != 0)
643 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
644 }
645 }
646
647 r = sd_bus_message_enter_container(message, 'a', "(sv)");
648 if (r < 0)
649 return r;
650
651 if (t == _SESSION_TYPE_INVALID) {
652 if (!isempty(display))
653 t = SESSION_X11;
654 else if (!isempty(tty))
655 t = SESSION_TTY;
656 else
657 t = SESSION_UNSPECIFIED;
658 }
659
660 if (c == _SESSION_CLASS_INVALID) {
661 if (t == SESSION_UNSPECIFIED)
662 c = SESSION_BACKGROUND;
663 else
664 c = SESSION_USER;
665 }
666
667 if (leader <= 0) {
668 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
669
670 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
671 if (r < 0)
672 return r;
673
674 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
675 if (r < 0)
676 return r;
677 }
678
679 manager_get_session_by_pid(m, leader, &session);
680 if (session) {
681 _cleanup_free_ char *path = NULL;
682 _cleanup_close_ int fifo_fd = -1;
683
684 /* Session already exists, client is probably
685 * something like "su" which changes uid but is still
686 * the same session */
687
688 fifo_fd = session_create_fifo(session);
689 if (fifo_fd < 0)
690 return fifo_fd;
691
692 path = session_bus_path(session);
693 if (!path)
694 return -ENOMEM;
695
696 log_debug("Sending reply about an existing session: "
697 "id=%s object_path=%s uid=%u runtime_path=%s "
698 "session_fd=%d seat=%s vtnr=%u",
699 session->id,
700 path,
701 (uint32_t) session->user->uid,
702 session->user->runtime_path,
703 fifo_fd,
704 session->seat ? session->seat->id : "",
705 (uint32_t) session->vtnr);
706
707 return sd_bus_reply_method_return(
708 message, "soshusub",
709 session->id,
710 path,
711 session->user->runtime_path,
712 fifo_fd,
713 (uint32_t) session->user->uid,
714 session->seat ? session->seat->id : "",
715 (uint32_t) session->vtnr,
716 true);
717 }
718
719 audit_session_from_pid(leader, &audit_id);
720 if (audit_id > 0) {
721 /* Keep our session IDs and the audit session IDs in sync */
722
723 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
724 return -ENOMEM;
725
726 /* Wut? There's already a session by this name and we
727 * didn't find it above? Weird, then let's not trust
728 * the audit data and let's better register a new
729 * ID */
730 if (hashmap_get(m->sessions, id)) {
731 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
732 audit_id = 0;
733
734 free(id);
735 id = NULL;
736 }
737 }
738
739 if (!id) {
740 do {
741 free(id);
742 id = NULL;
743
744 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
745 return -ENOMEM;
746
747 } while (hashmap_get(m->sessions, id));
748 }
749
750 r = manager_add_user_by_uid(m, uid, &user);
751 if (r < 0)
752 goto fail;
753
754 r = manager_add_session(m, id, &session);
755 if (r < 0)
756 goto fail;
757
758 session_set_user(session, user);
759
760 session->leader = leader;
761 session->audit_id = audit_id;
762 session->type = t;
763 session->class = c;
764 session->remote = remote;
765 session->vtnr = vtnr;
766
767 if (!isempty(tty)) {
768 session->tty = strdup(tty);
769 if (!session->tty) {
770 r = -ENOMEM;
771 goto fail;
772 }
773 }
774
775 if (!isempty(display)) {
776 session->display = strdup(display);
777 if (!session->display) {
778 r = -ENOMEM;
779 goto fail;
780 }
781 }
782
783 if (!isempty(remote_user)) {
784 session->remote_user = strdup(remote_user);
785 if (!session->remote_user) {
786 r = -ENOMEM;
787 goto fail;
788 }
789 }
790
791 if (!isempty(remote_host)) {
792 session->remote_host = strdup(remote_host);
793 if (!session->remote_host) {
794 r = -ENOMEM;
795 goto fail;
796 }
797 }
798
799 if (!isempty(service)) {
800 session->service = strdup(service);
801 if (!session->service) {
802 r = -ENOMEM;
803 goto fail;
804 }
805 }
806
807 if (!isempty(desktop)) {
808 session->desktop = strdup(desktop);
809 if (!session->desktop) {
810 r = -ENOMEM;
811 goto fail;
812 }
813 }
814
815 if (seat) {
816 r = seat_attach_session(seat, session);
817 if (r < 0)
818 goto fail;
819 }
820
821 r = session_start(session);
822 if (r < 0)
823 goto fail;
824
825 session->create_message = sd_bus_message_ref(message);
826
827 /* Now, let's wait until the slice unit and stuff got
828 * created. We send the reply back from
829 * session_send_create_reply(). */
830
831 return 1;
832
833fail:
834 if (session)
835 session_add_to_gc_queue(session);
836
837 if (user)
838 user_add_to_gc_queue(user);
839
840 return r;
841}
842
843static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
844 Manager *m = userdata;
845 Session *session;
846 const char *name;
847 int r;
848
849 assert(bus);
850 assert(message);
851 assert(m);
852
853 r = sd_bus_message_read(message, "s", &name);
854 if (r < 0)
855 return r;
856
857 r = manager_get_session_from_creds(m, message, name, error, &session);
858 if (r < 0)
859 return r;
860
861 r = session_release(session);
862 if (r < 0)
863 return r;
864
865 return sd_bus_reply_method_return(message, NULL);
866}
867
868static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
869 Manager *m = userdata;
870 Session *session;
871 const char *name;
872 int r;
873
874 assert(bus);
875 assert(message);
876 assert(m);
877
878 r = sd_bus_message_read(message, "s", &name);
879 if (r < 0)
880 return r;
881
882 r = manager_get_session_from_creds(m, message, name, error, &session);
883 if (r < 0)
884 return r;
885
886 return bus_session_method_activate(bus, message, session, error);
887}
888
889static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
890 const char *session_name, *seat_name;
891 Manager *m = userdata;
892 Session *session;
893 Seat *seat;
894 int r;
895
896 assert(bus);
897 assert(message);
898 assert(m);
899
900 /* Same as ActivateSession() but refuses to work if
901 * the seat doesn't match */
902
903 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
904 if (r < 0)
905 return r;
906
907 r = manager_get_session_from_creds(m, message, session_name, error, &session);
908 if (r < 0)
909 return r;
910
911 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
912 if (r < 0)
913 return r;
914
915 if (session->seat != seat)
916 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
917
918 r = session_activate(session);
919 if (r < 0)
920 return r;
921
922 return sd_bus_reply_method_return(message, NULL);
923}
924
925static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
926 Manager *m = userdata;
927 Session *session;
928 const char *name;
929 int r;
930
931 assert(bus);
932 assert(message);
933 assert(m);
934
935 r = sd_bus_message_read(message, "s", &name);
936 if (r < 0)
937 return r;
938
939 r = manager_get_session_from_creds(m, message, name, error, &session);
940 if (r < 0)
941 return r;
942
943 return bus_session_method_lock(bus, message, session, error);
944}
945
946static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
947 Manager *m = userdata;
948 int r;
949
950 assert(bus);
951 assert(message);
952 assert(m);
953
954 r = bus_verify_polkit_async(
955 message,
956 CAP_SYS_ADMIN,
957 "org.freedesktop.login1.lock-sessions",
958 false,
959 UID_INVALID,
960 &m->polkit_registry,
961 error);
962 if (r < 0)
963 return r;
964 if (r == 0)
965 return 1; /* Will call us back */
966
967 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
968 if (r < 0)
969 return r;
970
971 return sd_bus_reply_method_return(message, NULL);
972}
973
974static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
975 const char *name;
976 Manager *m = userdata;
977 Session *session;
978 int r;
979
980 assert(bus);
981 assert(message);
982 assert(m);
983
984 r = sd_bus_message_read(message, "s", &name);
985 if (r < 0)
986 return r;
987
988 r = manager_get_session_from_creds(m, message, name, error, &session);
989 if (r < 0)
990 return r;
991
992 return bus_session_method_kill(bus, message, session, error);
993}
994
995static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
996 Manager *m = userdata;
997 uint32_t uid;
998 User *user;
999 int r;
1000
1001 assert(bus);
1002 assert(message);
1003 assert(m);
1004
1005 r = sd_bus_message_read(message, "u", &uid);
1006 if (r < 0)
1007 return r;
1008
1009 r = manager_get_user_from_creds(m, message, uid, error, &user);
1010 if (r < 0)
1011 return r;
1012
1013 return bus_user_method_kill(bus, message, user, error);
1014}
1015
1016static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1017 Manager *m = userdata;
1018 const char *name;
1019 Session *session;
1020 int r;
1021
1022 assert(bus);
1023 assert(message);
1024 assert(m);
1025
1026 r = sd_bus_message_read(message, "s", &name);
1027 if (r < 0)
1028 return r;
1029
1030 r = manager_get_session_from_creds(m, message, name, error, &session);
1031 if (r < 0)
1032 return r;
1033
1034 return bus_session_method_terminate(bus, message, session, error);
1035}
1036
1037static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1038 Manager *m = userdata;
1039 uint32_t uid;
1040 User *user;
1041 int r;
1042
1043 assert(bus);
1044 assert(message);
1045 assert(m);
1046
1047 r = sd_bus_message_read(message, "u", &uid);
1048 if (r < 0)
1049 return r;
1050
1051 r = manager_get_user_from_creds(m, message, uid, error, &user);
1052 if (r < 0)
1053 return r;
1054
1055 return bus_user_method_terminate(bus, message, user, error);
1056}
1057
1058static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1059 Manager *m = userdata;
1060 const char *name;
1061 Seat *seat;
1062 int r;
1063
1064 assert(bus);
1065 assert(message);
1066 assert(m);
1067
1068 r = sd_bus_message_read(message, "s", &name);
1069 if (r < 0)
1070 return r;
1071
1072 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1073 if (r < 0)
1074 return r;
1075
1076 return bus_seat_method_terminate(bus, message, seat, error);
1077}
1078
1079static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1080 _cleanup_free_ char *cc = NULL;
1081 Manager *m = userdata;
1082 int b, r;
1083 struct passwd *pw;
1084 const char *path;
1085 uint32_t uid;
1086 int interactive;
1087
1088 assert(bus);
1089 assert(message);
1090 assert(m);
1091
1092 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1093 if (r < 0)
1094 return r;
1095
1096 if (uid == UID_INVALID) {
1097 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1098
1099 /* Note that we get the owner UID of the session, not the actual client UID here! */
1100 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1101 if (r < 0)
1102 return r;
1103
1104 r = sd_bus_creds_get_owner_uid(creds, &uid);
1105 if (r < 0)
1106 return r;
1107 }
1108
1109 errno = 0;
1110 pw = getpwuid(uid);
1111 if (!pw)
1112 return errno ? -errno : -ENOENT;
1113
1114 r = bus_verify_polkit_async(
1115 message,
1116 CAP_SYS_ADMIN,
1117 "org.freedesktop.login1.set-user-linger",
1118 interactive,
1119 UID_INVALID,
1120 &m->polkit_registry,
1121 error);
1122 if (r < 0)
1123 return r;
1124 if (r == 0)
1125 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1126
1127 mkdir_p_label("/var/lib/systemd", 0755);
1128
1129 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1130 if (r < 0)
1131 return r;
1132
1133 cc = cescape(pw->pw_name);
1134 if (!cc)
1135 return -ENOMEM;
1136
1137 path = strjoina("/var/lib/systemd/linger/", cc);
1138 if (b) {
1139 User *u;
1140
1141 r = touch(path);
1142 if (r < 0)
1143 return r;
1144
1145 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1146 user_start(u);
1147
1148 } else {
1149 User *u;
1150
1151 r = unlink(path);
1152 if (r < 0 && errno != ENOENT)
1153 return -errno;
1154
1155 u = hashmap_get(m->users, UID_TO_PTR(uid));
1156 if (u)
1157 user_add_to_gc_queue(u);
1158 }
1159
1160 return sd_bus_reply_method_return(message, NULL);
1161}
1162
1163static int trigger_device(Manager *m, struct udev_device *d) {
1164 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1165 struct udev_list_entry *first, *item;
1166 int r;
1167
1168 assert(m);
1169
1170 e = udev_enumerate_new(m->udev);
1171 if (!e)
1172 return -ENOMEM;
1173
1174 if (d) {
1175 r = udev_enumerate_add_match_parent(e, d);
1176 if (r < 0)
1177 return r;
1178 }
1179
1180 r = udev_enumerate_scan_devices(e);
1181 if (r < 0)
1182 return r;
1183
1184 first = udev_enumerate_get_list_entry(e);
1185 udev_list_entry_foreach(item, first) {
1186 _cleanup_free_ char *t = NULL;
1187 const char *p;
1188
1189 p = udev_list_entry_get_name(item);
1190
1191 t = strappend(p, "/uevent");
1192 if (!t)
1193 return -ENOMEM;
1194
1195 write_string_file(t, "change");
1196 }
1197
1198 return 0;
1199}
1200
1201static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1202 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1203 _cleanup_free_ char *rule = NULL, *file = NULL;
1204 const char *id_for_seat;
1205 int r;
1206
1207 assert(m);
1208 assert(seat);
1209 assert(sysfs);
1210
1211 d = udev_device_new_from_syspath(m->udev, sysfs);
1212 if (!d)
1213 return -ENODEV;
1214
1215 if (!udev_device_has_tag(d, "seat"))
1216 return -ENODEV;
1217
1218 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1219 if (!id_for_seat)
1220 return -ENODEV;
1221
1222 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1223 return -ENOMEM;
1224
1225 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1226 return -ENOMEM;
1227
1228 mkdir_p_label("/etc/udev/rules.d", 0755);
1229 mac_selinux_init("/etc");
1230 r = write_string_file_atomic_label(file, rule);
1231 if (r < 0)
1232 return r;
1233
1234 return trigger_device(m, d);
1235}
1236
1237static int flush_devices(Manager *m) {
1238 _cleanup_closedir_ DIR *d;
1239
1240 assert(m);
1241
1242 d = opendir("/etc/udev/rules.d");
1243 if (!d) {
1244 if (errno != ENOENT)
1245 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1246 } else {
1247 struct dirent *de;
1248
1249 while ((de = readdir(d))) {
1250
1251 if (!dirent_is_file(de))
1252 continue;
1253
1254 if (!startswith(de->d_name, "72-seat-"))
1255 continue;
1256
1257 if (!endswith(de->d_name, ".rules"))
1258 continue;
1259
1260 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1261 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1262 }
1263 }
1264
1265 return trigger_device(m, NULL);
1266}
1267
1268static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1269 const char *sysfs, *seat;
1270 Manager *m = userdata;
1271 int interactive, r;
1272
1273 assert(bus);
1274 assert(message);
1275 assert(m);
1276
1277 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1278 if (r < 0)
1279 return r;
1280
1281 if (!path_startswith(sysfs, "/sys"))
1282 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1283
1284 if (!seat_name_is_valid(seat))
1285 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1286
1287 r = bus_verify_polkit_async(
1288 message,
1289 CAP_SYS_ADMIN,
1290 "org.freedesktop.login1.attach-device",
1291 interactive,
1292 UID_INVALID,
1293 &m->polkit_registry,
1294 error);
1295 if (r < 0)
1296 return r;
1297 if (r == 0)
1298 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1299
1300 r = attach_device(m, seat, sysfs);
1301 if (r < 0)
1302 return r;
1303
1304 return sd_bus_reply_method_return(message, NULL);
1305}
1306
1307static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1308 Manager *m = userdata;
1309 int interactive, r;
1310
1311 assert(bus);
1312 assert(message);
1313 assert(m);
1314
1315 r = sd_bus_message_read(message, "b", &interactive);
1316 if (r < 0)
1317 return r;
1318
1319 r = bus_verify_polkit_async(
1320 message,
1321 CAP_SYS_ADMIN,
1322 "org.freedesktop.login1.flush-devices",
1323 interactive,
1324 UID_INVALID,
1325 &m->polkit_registry,
1326 error);
1327 if (r < 0)
1328 return r;
1329 if (r == 0)
1330 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1331
1332 r = flush_devices(m);
1333 if (r < 0)
1334 return r;
1335
1336 return sd_bus_reply_method_return(message, NULL);
1337}
1338
1339static int have_multiple_sessions(
1340 Manager *m,
1341 uid_t uid) {
1342
1343 Session *session;
1344 Iterator i;
1345
1346 assert(m);
1347
1348 /* Check for other users' sessions. Greeter sessions do not
1349 * count, and non-login sessions do not count either. */
1350 HASHMAP_FOREACH(session, m->sessions, i)
1351 if (session->class == SESSION_USER &&
1352 session->user->uid != uid)
1353 return true;
1354
1355 return false;
1356}
1357
1358static int bus_manager_log_shutdown(
1359 Manager *m,
1360 InhibitWhat w,
1361 const char *unit_name) {
1362
1363 const char *p, *q;
1364
1365 assert(m);
1366 assert(unit_name);
1367
1368 if (w != INHIBIT_SHUTDOWN)
1369 return 0;
1370
1371 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1372 p = "MESSAGE=System is powering down.";
1373 q = "SHUTDOWN=power-off";
1374 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1375 p = "MESSAGE=System is halting.";
1376 q = "SHUTDOWN=halt";
1377 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1378 p = "MESSAGE=System is rebooting.";
1379 q = "SHUTDOWN=reboot";
1380 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1381 p = "MESSAGE=System is rebooting with kexec.";
1382 q = "SHUTDOWN=kexec";
1383 } else {
1384 p = "MESSAGE=System is shutting down.";
1385 q = NULL;
1386 }
1387
1388 return log_struct(LOG_NOTICE,
1389 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1390 p,
1391 q,
1392 NULL);
1393}
1394
1395static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1396 Manager *m = userdata;
1397
1398 assert(e);
1399 assert(m);
1400
1401 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1402 return 0;
1403}
1404
1405int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1406 int r;
1407
1408 assert(m);
1409
1410 if (until <= now(CLOCK_MONOTONIC))
1411 return 0;
1412
1413 /* We want to ignore the lid switch for a while after each
1414 * suspend, and after boot-up. Hence let's install a timer for
1415 * this. As long as the event source exists we ignore the lid
1416 * switch. */
1417
1418 if (m->lid_switch_ignore_event_source) {
1419 usec_t u;
1420
1421 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1422 if (r < 0)
1423 return r;
1424
1425 if (until <= u)
1426 return 0;
1427
1428 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1429 } else
1430 r = sd_event_add_time(
1431 m->event,
1432 &m->lid_switch_ignore_event_source,
1433 CLOCK_MONOTONIC,
1434 until, 0,
1435 lid_switch_ignore_handler, m);
1436
1437 return r;
1438}
1439
1440static int execute_shutdown_or_sleep(
1441 Manager *m,
1442 InhibitWhat w,
1443 const char *unit_name,
1444 sd_bus_error *error) {
1445
1446 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1447 const char *p;
1448 char *c;
1449 int r;
1450
1451 assert(m);
1452 assert(w >= 0);
1453 assert(w < _INHIBIT_WHAT_MAX);
1454 assert(unit_name);
1455
1456 bus_manager_log_shutdown(m, w, unit_name);
1457
1458 r = sd_bus_call_method(
1459 m->bus,
1460 "org.freedesktop.systemd1",
1461 "/org/freedesktop/systemd1",
1462 "org.freedesktop.systemd1.Manager",
1463 "StartUnit",
1464 error,
1465 &reply,
1466 "ss", unit_name, "replace-irreversibly");
1467 if (r < 0)
1468 return r;
1469
1470 r = sd_bus_message_read(reply, "o", &p);
1471 if (r < 0)
1472 return r;
1473
1474 c = strdup(p);
1475 if (!c)
1476 return -ENOMEM;
1477
1478 m->action_unit = unit_name;
1479 free(m->action_job);
1480 m->action_job = c;
1481 m->action_what = w;
1482
1483 /* Make sure the lid switch is ignored for a while */
1484 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1485
1486 return 0;
1487}
1488
1489static int manager_inhibit_timeout_handler(
1490 sd_event_source *s,
1491 uint64_t usec,
1492 void *userdata) {
1493
1494 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1495 Inhibitor *offending = NULL;
1496 Manager *manager = userdata;
1497 int r;
1498
1499 assert(manager);
1500 assert(manager->inhibit_timeout_source == s);
1501
1502 if (manager->action_what == 0 || manager->action_job)
1503 return 0;
1504
1505 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1506 _cleanup_free_ char *comm = NULL, *u = NULL;
1507
1508 (void) get_process_comm(offending->pid, &comm);
1509 u = uid_to_name(offending->uid);
1510
1511 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1512 offending->uid, strna(u),
1513 offending->pid, strna(comm));
1514 }
1515
1516 /* Actually do the operation */
1517 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1518 if (r < 0) {
1519 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1520
1521 manager->action_unit = NULL;
1522 manager->action_what = 0;
1523 }
1524
1525 return 0;
1526}
1527
1528static int delay_shutdown_or_sleep(
1529 Manager *m,
1530 InhibitWhat w,
1531 const char *unit_name) {
1532
1533 int r;
1534 usec_t timeout_val;
1535
1536 assert(m);
1537 assert(w >= 0);
1538 assert(w < _INHIBIT_WHAT_MAX);
1539 assert(unit_name);
1540
1541 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1542
1543 if (m->inhibit_timeout_source) {
1544 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1545 if (r < 0)
1546 return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
1547
1548 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1549 if (r < 0)
1550 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
1551 } else {
1552 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1553 timeout_val, 0, manager_inhibit_timeout_handler, m);
1554 if (r < 0)
1555 return r;
1556 }
1557
1558 m->action_unit = unit_name;
1559 m->action_what = w;
1560
1561 return 0;
1562}
1563
1564static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1565
1566 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1567 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1568 [INHIBIT_SLEEP] = "PrepareForSleep"
1569 };
1570
1571 int active = _active;
1572
1573 assert(m);
1574 assert(w >= 0);
1575 assert(w < _INHIBIT_WHAT_MAX);
1576 assert(signal_name[w]);
1577
1578 return sd_bus_emit_signal(m->bus,
1579 "/org/freedesktop/login1",
1580 "org.freedesktop.login1.Manager",
1581 signal_name[w],
1582 "b",
1583 active);
1584}
1585
1586int bus_manager_shutdown_or_sleep_now_or_later(
1587 Manager *m,
1588 const char *unit_name,
1589 InhibitWhat w,
1590 sd_bus_error *error) {
1591
1592 bool delayed;
1593 int r;
1594
1595 assert(m);
1596 assert(unit_name);
1597 assert(w >= 0);
1598 assert(w <= _INHIBIT_WHAT_MAX);
1599 assert(!m->action_job);
1600
1601 /* Tell everybody to prepare for shutdown/sleep */
1602 send_prepare_for(m, w, true);
1603
1604 delayed =
1605 m->inhibit_delay_max > 0 &&
1606 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1607
1608 if (delayed)
1609 /* Shutdown is delayed, keep in mind what we
1610 * want to do, and start a timeout */
1611 r = delay_shutdown_or_sleep(m, w, unit_name);
1612 else
1613 /* Shutdown is not delayed, execute it
1614 * immediately */
1615 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1616
1617 return r;
1618}
1619
1620static int verify_shutdown_creds(
1621 Manager *m,
1622 sd_bus_message *message,
1623 InhibitWhat w,
1624 bool interactive,
1625 const char *action,
1626 const char *action_multiple_sessions,
1627 const char *action_ignore_inhibit,
1628 sd_bus_error *error) {
1629
1630 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1631 bool multiple_sessions, blocked;
1632 uid_t uid;
1633 int r;
1634
1635 assert(m);
1636 assert(message);
1637 assert(w >= 0);
1638 assert(w <= _INHIBIT_WHAT_MAX);
1639
1640 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1641 if (r < 0)
1642 return r;
1643
1644 r = sd_bus_creds_get_euid(creds, &uid);
1645 if (r < 0)
1646 return r;
1647
1648 r = have_multiple_sessions(m, uid);
1649 if (r < 0)
1650 return r;
1651
1652 multiple_sessions = r > 0;
1653 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1654
1655 if (multiple_sessions && action_multiple_sessions) {
1656 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1657 if (r < 0)
1658 return r;
1659 if (r == 0)
1660 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1661 }
1662
1663 if (blocked && action_ignore_inhibit) {
1664 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1665 if (r < 0)
1666 return r;
1667 if (r == 0)
1668 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1669 }
1670
1671 if (!multiple_sessions && !blocked && action) {
1672 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1673 if (r < 0)
1674 return r;
1675 if (r == 0)
1676 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1677 }
1678
1679 return 0;
1680}
1681
1682static int method_do_shutdown_or_sleep(
1683 Manager *m,
1684 sd_bus_message *message,
1685 const char *unit_name,
1686 InhibitWhat w,
1687 const char *action,
1688 const char *action_multiple_sessions,
1689 const char *action_ignore_inhibit,
1690 const char *sleep_verb,
1691 sd_bus_error *error) {
1692
1693 int interactive, r;
1694
1695 assert(m);
1696 assert(message);
1697 assert(unit_name);
1698 assert(w >= 0);
1699 assert(w <= _INHIBIT_WHAT_MAX);
1700
1701 r = sd_bus_message_read(message, "b", &interactive);
1702 if (r < 0)
1703 return r;
1704
1705 /* Don't allow multiple jobs being executed at the same time */
1706 if (m->action_what)
1707 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1708
1709 if (sleep_verb) {
1710 r = can_sleep(sleep_verb);
1711 if (r < 0)
1712 return r;
1713
1714 if (r == 0)
1715 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1716 }
1717
1718 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1719 action_ignore_inhibit, error);
1720 if (r != 0)
1721 return r;
1722
1723 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1724 if (r < 0)
1725 return r;
1726
1727 return sd_bus_reply_method_return(message, NULL);
1728}
1729
1730static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1731 Manager *m = userdata;
1732
1733 return method_do_shutdown_or_sleep(
1734 m, message,
1735 SPECIAL_POWEROFF_TARGET,
1736 INHIBIT_SHUTDOWN,
1737 "org.freedesktop.login1.power-off",
1738 "org.freedesktop.login1.power-off-multiple-sessions",
1739 "org.freedesktop.login1.power-off-ignore-inhibit",
1740 NULL,
1741 error);
1742}
1743
1744static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1745 Manager *m = userdata;
1746
1747 return method_do_shutdown_or_sleep(
1748 m, message,
1749 SPECIAL_REBOOT_TARGET,
1750 INHIBIT_SHUTDOWN,
1751 "org.freedesktop.login1.reboot",
1752 "org.freedesktop.login1.reboot-multiple-sessions",
1753 "org.freedesktop.login1.reboot-ignore-inhibit",
1754 NULL,
1755 error);
1756}
1757
1758static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1759 Manager *m = userdata;
1760
1761 return method_do_shutdown_or_sleep(
1762 m, message,
1763 SPECIAL_SUSPEND_TARGET,
1764 INHIBIT_SLEEP,
1765 "org.freedesktop.login1.suspend",
1766 "org.freedesktop.login1.suspend-multiple-sessions",
1767 "org.freedesktop.login1.suspend-ignore-inhibit",
1768 "suspend",
1769 error);
1770}
1771
1772static int manager_scheduled_shutdown_handler(
1773 sd_event_source *s,
1774 uint64_t usec,
1775 void *userdata) {
1776
1777 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1778 Manager *m = userdata;
1779 const char *target;
1780 int r;
1781
1782 assert(m);
1783
1784 if (isempty(m->scheduled_shutdown_type))
1785 return 0;
1786
1787 if (streq(m->scheduled_shutdown_type, "halt"))
1788 target = SPECIAL_HALT_TARGET;
1789 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1790 target = SPECIAL_POWEROFF_TARGET;
1791 else
1792 target = SPECIAL_REBOOT_TARGET;
1793
1794 r = execute_shutdown_or_sleep(m, 0, target, &error);
1795 if (r < 0)
1796 return log_error_errno(r, "Unable to execute transition to %s: %m\n", target);
1797
1798 return 0;
1799}
1800
1801static int method_schedule_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1802 Manager *m = userdata;
1803 const char *action_multiple_sessions = NULL;
1804 const char *action_ignore_inhibit = NULL;
1805 const char *action = NULL;
1806 uint64_t elapse;
1807 char *type;
1808 int r;
1809
1810 assert(m);
1811 assert(message);
1812
1813 r = sd_bus_message_read(message, "st", &type, &elapse);
1814 if (r < 0)
1815 return r;
1816
1817 if (streq(type, "reboot")) {
1818 action = "org.freedesktop.login1.reboot";
1819 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1820 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1821 } else if (streq(type, "halt")) {
1822 action = "org.freedesktop.login1.halt";
1823 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1824 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1825 } else if (streq(type, "poweroff")) {
1826 action = "org.freedesktop.login1.poweroff";
1827 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1828 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1829 } else
1830 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1831
1832 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1833 action, action_multiple_sessions, action_ignore_inhibit, error);
1834 if (r != 0)
1835 return r;
1836
1837 if (m->scheduled_shutdown_timeout_source) {
1838 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1839 if (r < 0)
1840 return log_error_errno(r, "sd_event_source_set_time() failed: %m\n");
1841
1842 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
1843 if (r < 0)
1844 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m\n");
1845 } else {
1846 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
1847 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
1848 if (r < 0)
1849 return log_error_errno(r, "sd_event_add_time() failed: %m\n");
1850 }
1851
1852 r = free_and_strdup(&m->scheduled_shutdown_type, type);
1853 if (r < 0) {
1854 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1855 return log_oom();
1856 }
1857
1858 m->scheduled_shutdown_timeout = elapse;
1859
1860 return sd_bus_reply_method_return(message, NULL);
1861}
1862
1863static int method_cancel_scheduled_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1864 Manager *m = userdata;
1865 bool cancelled;
1866
1867 assert(m);
1868 assert(message);
1869
1870 cancelled = m->scheduled_shutdown_type != NULL;
1871
1872 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1873 free(m->scheduled_shutdown_type);
1874 m->scheduled_shutdown_type = NULL;
1875 m->scheduled_shutdown_timeout = 0;
1876
1877 return sd_bus_reply_method_return(message, "b", cancelled);
1878}
1879
1880static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1881 Manager *m = userdata;
1882
1883 return method_do_shutdown_or_sleep(
1884 m, message,
1885 SPECIAL_HIBERNATE_TARGET,
1886 INHIBIT_SLEEP,
1887 "org.freedesktop.login1.hibernate",
1888 "org.freedesktop.login1.hibernate-multiple-sessions",
1889 "org.freedesktop.login1.hibernate-ignore-inhibit",
1890 "hibernate",
1891 error);
1892}
1893
1894static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1895 Manager *m = userdata;
1896
1897 return method_do_shutdown_or_sleep(
1898 m, message,
1899 SPECIAL_HYBRID_SLEEP_TARGET,
1900 INHIBIT_SLEEP,
1901 "org.freedesktop.login1.hibernate",
1902 "org.freedesktop.login1.hibernate-multiple-sessions",
1903 "org.freedesktop.login1.hibernate-ignore-inhibit",
1904 "hybrid-sleep",
1905 error);
1906}
1907
1908static int method_can_shutdown_or_sleep(
1909 Manager *m,
1910 sd_bus_message *message,
1911 InhibitWhat w,
1912 const char *action,
1913 const char *action_multiple_sessions,
1914 const char *action_ignore_inhibit,
1915 const char *sleep_verb,
1916 sd_bus_error *error) {
1917
1918 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1919 bool multiple_sessions, challenge, blocked;
1920 const char *result = NULL;
1921 uid_t uid;
1922 int r;
1923
1924 assert(m);
1925 assert(message);
1926 assert(w >= 0);
1927 assert(w <= _INHIBIT_WHAT_MAX);
1928 assert(action);
1929 assert(action_multiple_sessions);
1930 assert(action_ignore_inhibit);
1931
1932 if (sleep_verb) {
1933 r = can_sleep(sleep_verb);
1934 if (r < 0)
1935 return r;
1936 if (r == 0)
1937 return sd_bus_reply_method_return(message, "s", "na");
1938 }
1939
1940 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1941 if (r < 0)
1942 return r;
1943
1944 r = sd_bus_creds_get_euid(creds, &uid);
1945 if (r < 0)
1946 return r;
1947
1948 r = have_multiple_sessions(m, uid);
1949 if (r < 0)
1950 return r;
1951
1952 multiple_sessions = r > 0;
1953 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1954
1955 if (multiple_sessions) {
1956 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
1957 if (r < 0)
1958 return r;
1959
1960 if (r > 0)
1961 result = "yes";
1962 else if (challenge)
1963 result = "challenge";
1964 else
1965 result = "no";
1966 }
1967
1968 if (blocked) {
1969 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
1970 if (r < 0)
1971 return r;
1972
1973 if (r > 0 && !result)
1974 result = "yes";
1975 else if (challenge && (!result || streq(result, "yes")))
1976 result = "challenge";
1977 else
1978 result = "no";
1979 }
1980
1981 if (!multiple_sessions && !blocked) {
1982 /* If neither inhibit nor multiple sessions
1983 * apply then just check the normal policy */
1984
1985 r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
1986 if (r < 0)
1987 return r;
1988
1989 if (r > 0)
1990 result = "yes";
1991 else if (challenge)
1992 result = "challenge";
1993 else
1994 result = "no";
1995 }
1996
1997 return sd_bus_reply_method_return(message, "s", result);
1998}
1999
2000static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2001 Manager *m = userdata;
2002
2003 return method_can_shutdown_or_sleep(
2004 m, message,
2005 INHIBIT_SHUTDOWN,
2006 "org.freedesktop.login1.power-off",
2007 "org.freedesktop.login1.power-off-multiple-sessions",
2008 "org.freedesktop.login1.power-off-ignore-inhibit",
2009 NULL,
2010 error);
2011}
2012
2013static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2014 Manager *m = userdata;
2015
2016 return method_can_shutdown_or_sleep(
2017 m, message,
2018 INHIBIT_SHUTDOWN,
2019 "org.freedesktop.login1.reboot",
2020 "org.freedesktop.login1.reboot-multiple-sessions",
2021 "org.freedesktop.login1.reboot-ignore-inhibit",
2022 NULL,
2023 error);
2024}
2025
2026static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2027 Manager *m = userdata;
2028
2029 return method_can_shutdown_or_sleep(
2030 m, message,
2031 INHIBIT_SLEEP,
2032 "org.freedesktop.login1.suspend",
2033 "org.freedesktop.login1.suspend-multiple-sessions",
2034 "org.freedesktop.login1.suspend-ignore-inhibit",
2035 "suspend",
2036 error);
2037}
2038
2039static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2040 Manager *m = userdata;
2041
2042 return method_can_shutdown_or_sleep(
2043 m, message,
2044 INHIBIT_SLEEP,
2045 "org.freedesktop.login1.hibernate",
2046 "org.freedesktop.login1.hibernate-multiple-sessions",
2047 "org.freedesktop.login1.hibernate-ignore-inhibit",
2048 "hibernate",
2049 error);
2050}
2051
2052static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2053 Manager *m = userdata;
2054
2055 return method_can_shutdown_or_sleep(
2056 m, message,
2057 INHIBIT_SLEEP,
2058 "org.freedesktop.login1.hibernate",
2059 "org.freedesktop.login1.hibernate-multiple-sessions",
2060 "org.freedesktop.login1.hibernate-ignore-inhibit",
2061 "hybrid-sleep",
2062 error);
2063}
2064
2065static int property_get_reboot_to_firmware_setup(
2066 sd_bus *bus,
2067 const char *path,
2068 const char *interface,
2069 const char *property,
2070 sd_bus_message *reply,
2071 void *userdata,
2072 sd_bus_error *error) {
2073 int r;
2074
2075 assert(bus);
2076 assert(reply);
2077 assert(userdata);
2078
2079 r = efi_get_reboot_to_firmware();
2080 if (r < 0 && r != -EOPNOTSUPP)
2081 return r;
2082
2083 return sd_bus_message_append(reply, "b", r > 0);
2084}
2085
2086static int method_set_reboot_to_firmware_setup(
2087 sd_bus *bus,
2088 sd_bus_message *message,
2089 void *userdata,
2090 sd_bus_error *error) {
2091
2092 int b, r;
2093 Manager *m = userdata;
2094
2095 assert(bus);
2096 assert(message);
2097 assert(m);
2098
2099 r = sd_bus_message_read(message, "b", &b);
2100 if (r < 0)
2101 return r;
2102
2103 r = bus_verify_polkit_async(message,
2104 CAP_SYS_ADMIN,
2105 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2106 false,
2107 UID_INVALID,
2108 &m->polkit_registry,
2109 error);
2110 if (r < 0)
2111 return r;
2112 if (r == 0)
2113 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2114
2115 r = efi_set_reboot_to_firmware(b);
2116 if (r < 0)
2117 return r;
2118
2119 return sd_bus_reply_method_return(message, NULL);
2120}
2121
2122static int method_can_reboot_to_firmware_setup(
2123 sd_bus *bus,
2124 sd_bus_message *message,
2125 void *userdata,
2126 sd_bus_error *error) {
2127
2128 int r;
2129 bool challenge;
2130 const char *result;
2131 Manager *m = userdata;
2132
2133 assert(bus);
2134 assert(message);
2135 assert(m);
2136
2137 r = efi_reboot_to_firmware_supported();
2138 if (r == -EOPNOTSUPP)
2139 return sd_bus_reply_method_return(message, "s", "na");
2140 else if (r < 0)
2141 return r;
2142
2143 r = bus_test_polkit(message,
2144 CAP_SYS_ADMIN,
2145 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2146 UID_INVALID,
2147 &challenge,
2148 error);
2149 if (r < 0)
2150 return r;
2151
2152 if (r > 0)
2153 result = "yes";
2154 else if (challenge)
2155 result = "challenge";
2156 else
2157 result = "no";
2158
2159 return sd_bus_reply_method_return(message, "s", result);
2160}
2161
2162static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2163 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2164 const char *who, *why, *what, *mode;
2165 _cleanup_free_ char *id = NULL;
2166 _cleanup_close_ int fifo_fd = -1;
2167 Manager *m = userdata;
2168 Inhibitor *i = NULL;
2169 InhibitMode mm;
2170 InhibitWhat w;
2171 pid_t pid;
2172 uid_t uid;
2173 int r;
2174
2175 assert(bus);
2176 assert(message);
2177 assert(m);
2178
2179 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2180 if (r < 0)
2181 return r;
2182
2183 w = inhibit_what_from_string(what);
2184 if (w <= 0)
2185 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2186
2187 mm = inhibit_mode_from_string(mode);
2188 if (mm < 0)
2189 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2190
2191 /* Delay is only supported for shutdown/sleep */
2192 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2193 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2194
2195 /* Don't allow taking delay locks while we are already
2196 * executing the operation. We shouldn't create the impression
2197 * that the lock was successful if the machine is about to go
2198 * down/suspend any moment. */
2199 if (m->action_what & w)
2200 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2201
2202 r = bus_verify_polkit_async(
2203 message,
2204 CAP_SYS_BOOT,
2205 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2206 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2207 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2208 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2209 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2210 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2211 "org.freedesktop.login1.inhibit-handle-lid-switch",
2212 false,
2213 UID_INVALID,
2214 &m->polkit_registry,
2215 error);
2216 if (r < 0)
2217 return r;
2218 if (r == 0)
2219 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2220
2221 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2222 if (r < 0)
2223 return r;
2224
2225 r = sd_bus_creds_get_euid(creds, &uid);
2226 if (r < 0)
2227 return r;
2228
2229 r = sd_bus_creds_get_pid(creds, &pid);
2230 if (r < 0)
2231 return r;
2232
2233 do {
2234 free(id);
2235 id = NULL;
2236
2237 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2238 return -ENOMEM;
2239
2240 } while (hashmap_get(m->inhibitors, id));
2241
2242 r = manager_add_inhibitor(m, id, &i);
2243 if (r < 0)
2244 return r;
2245
2246 i->what = w;
2247 i->mode = mm;
2248 i->pid = pid;
2249 i->uid = uid;
2250 i->why = strdup(why);
2251 i->who = strdup(who);
2252
2253 if (!i->why || !i->who) {
2254 r = -ENOMEM;
2255 goto fail;
2256 }
2257
2258 fifo_fd = inhibitor_create_fifo(i);
2259 if (fifo_fd < 0) {
2260 r = fifo_fd;
2261 goto fail;
2262 }
2263
2264 inhibitor_start(i);
2265
2266 return sd_bus_reply_method_return(message, "h", fifo_fd);
2267
2268fail:
2269 if (i)
2270 inhibitor_free(i);
2271
2272 return r;
2273}
2274
2275const sd_bus_vtable manager_vtable[] = {
2276 SD_BUS_VTABLE_START(0),
2277
2278 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2279 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2280 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2281 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2282 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2283 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2284 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2285 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2286 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2287 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2288 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2289 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2290 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2291 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2292 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2293 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2294 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2295 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2296 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2297 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2298 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2299 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2300
2301 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2302 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2303 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2304 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2305 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2306 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2307 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2308 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2309 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2310 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2311 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2312 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2313 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2314 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2315 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2316 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2317 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2318 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2319 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2320 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2321 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2322 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2323 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2324 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2325 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2326 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2327 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2328 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2329 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2330 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2331 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2332 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2333 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2334 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2335 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2336 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2337 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2338 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2339 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2340 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2341
2342 SD_BUS_SIGNAL("SessionNew", "so", 0),
2343 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2344 SD_BUS_SIGNAL("UserNew", "uo", 0),
2345 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2346 SD_BUS_SIGNAL("SeatNew", "so", 0),
2347 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2348 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2349 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2350
2351 SD_BUS_VTABLE_END
2352};
2353
2354static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2355 int r = 0;
2356
2357 assert(s);
2358 assert(unit);
2359
2360 if (!s->started)
2361 return r;
2362
2363 if (streq(result, "done"))
2364 r = session_send_create_reply(s, NULL);
2365 else {
2366 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2367
2368 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2369 r = session_send_create_reply(s, &e);
2370 }
2371
2372 return r;
2373}
2374
2375int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2376 const char *path, *result, *unit;
2377 Manager *m = userdata;
2378 Session *session;
2379 uint32_t id;
2380 User *user;
2381 int r;
2382
2383 assert(bus);
2384 assert(message);
2385 assert(m);
2386
2387 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2388 if (r < 0) {
2389 bus_log_parse_error(r);
2390 return r;
2391 }
2392
2393 if (m->action_job && streq(m->action_job, path)) {
2394 log_info("Operation finished.");
2395
2396 /* Tell people that they now may take a lock again */
2397 send_prepare_for(m, m->action_what, false);
2398
2399 free(m->action_job);
2400 m->action_job = NULL;
2401 m->action_unit = NULL;
2402 m->action_what = 0;
2403 return 0;
2404 }
2405
2406 session = hashmap_get(m->session_units, unit);
2407 if (session) {
2408
2409 if (streq_ptr(path, session->scope_job)) {
2410 free(session->scope_job);
2411 session->scope_job = NULL;
2412 }
2413
2414 session_jobs_reply(session, unit, result);
2415
2416 session_save(session);
2417 session_add_to_gc_queue(session);
2418 }
2419
2420 user = hashmap_get(m->user_units, unit);
2421 if (user) {
2422
2423 if (streq_ptr(path, user->service_job)) {
2424 free(user->service_job);
2425 user->service_job = NULL;
2426 }
2427
2428 if (streq_ptr(path, user->slice_job)) {
2429 free(user->slice_job);
2430 user->slice_job = NULL;
2431 }
2432
2433 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2434 session_jobs_reply(session, unit, result);
2435 }
2436
2437 user_save(user);
2438 user_add_to_gc_queue(user);
2439 }
2440
2441 return 0;
2442}
2443
2444int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2445 const char *path, *unit;
2446 Manager *m = userdata;
2447 Session *session;
2448 User *user;
2449 int r;
2450
2451 assert(bus);
2452 assert(message);
2453 assert(m);
2454
2455 r = sd_bus_message_read(message, "so", &unit, &path);
2456 if (r < 0) {
2457 bus_log_parse_error(r);
2458 return r;
2459 }
2460
2461 session = hashmap_get(m->session_units, unit);
2462 if (session)
2463 session_add_to_gc_queue(session);
2464
2465 user = hashmap_get(m->user_units, unit);
2466 if (user)
2467 user_add_to_gc_queue(user);
2468
2469 return 0;
2470}
2471
2472int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2473 _cleanup_free_ char *unit = NULL;
2474 Manager *m = userdata;
2475 const char *path;
2476 Session *session;
2477 User *user;
2478 int r;
2479
2480 assert(bus);
2481 assert(message);
2482 assert(m);
2483
2484 path = sd_bus_message_get_path(message);
2485 if (!path)
2486 return 0;
2487
2488 r = unit_name_from_dbus_path(path, &unit);
2489 if (r == -EINVAL) /* not a unit */
2490 return 0;
2491 if (r < 0)
2492 return r;
2493
2494 session = hashmap_get(m->session_units, unit);
2495 if (session)
2496 session_add_to_gc_queue(session);
2497
2498 user = hashmap_get(m->user_units, unit);
2499 if (user)
2500 user_add_to_gc_queue(user);
2501
2502 return 0;
2503}
2504
2505int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2506 Manager *m = userdata;
2507 Session *session;
2508 Iterator i;
2509 int b, r;
2510
2511 assert(bus);
2512
2513 r = sd_bus_message_read(message, "b", &b);
2514 if (r < 0) {
2515 bus_log_parse_error(r);
2516 return r;
2517 }
2518
2519 if (b)
2520 return 0;
2521
2522 /* systemd finished reloading, let's recheck all our sessions */
2523 log_debug("System manager has been reloaded, rechecking sessions...");
2524
2525 HASHMAP_FOREACH(session, m->sessions, i)
2526 session_add_to_gc_queue(session);
2527
2528 return 0;
2529}
2530
2531int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
2532 const char *name, *old, *new;
2533 Manager *m = userdata;
2534 Session *session;
2535 Iterator i;
2536 int r;
2537
2538
2539 char *key;
2540
2541 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2542 if (r < 0) {
2543 bus_log_parse_error(r);
2544 return r;
2545 }
2546
2547 if (isempty(old) || !isempty(new))
2548 return 0;
2549
2550 key = set_remove(m->busnames, (char*) old);
2551 if (!key)
2552 return 0;
2553
2554 /* Drop all controllers owned by this name */
2555
2556 free(key);
2557
2558 HASHMAP_FOREACH(session, m->sessions, i)
2559 if (session_is_controller(session, old))
2560 session_drop_controller(session);
2561
2562 return 0;
2563}
2564
2565int manager_send_changed(Manager *manager, const char *property, ...) {
2566 char **l;
2567
2568 assert(manager);
2569
2570 l = strv_from_stdarg_alloca(property);
2571
2572 return sd_bus_emit_properties_changed_strv(
2573 manager->bus,
2574 "/org/freedesktop/login1",
2575 "org.freedesktop.login1.Manager",
2576 l);
2577}
2578
2579int manager_start_scope(
2580 Manager *manager,
2581 const char *scope,
2582 pid_t pid,
2583 const char *slice,
2584 const char *description,
2585 const char *after, const char *after2,
2586 sd_bus_error *error,
2587 char **job) {
2588
2589 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2590 int r;
2591
2592 assert(manager);
2593 assert(scope);
2594 assert(pid > 1);
2595
2596 r = sd_bus_message_new_method_call(
2597 manager->bus,
2598 &m,
2599 "org.freedesktop.systemd1",
2600 "/org/freedesktop/systemd1",
2601 "org.freedesktop.systemd1.Manager",
2602 "StartTransientUnit");
2603 if (r < 0)
2604 return r;
2605
2606 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2607 if (r < 0)
2608 return r;
2609
2610 r = sd_bus_message_open_container(m, 'a', "(sv)");
2611 if (r < 0)
2612 return r;
2613
2614 if (!isempty(slice)) {
2615 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2616 if (r < 0)
2617 return r;
2618 }
2619
2620 if (!isempty(description)) {
2621 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2622 if (r < 0)
2623 return r;
2624 }
2625
2626 if (!isempty(after)) {
2627 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2628 if (r < 0)
2629 return r;
2630 }
2631
2632 if (!isempty(after2)) {
2633 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2634 if (r < 0)
2635 return r;
2636 }
2637
2638 /* cgroup empty notification is not available in containers
2639 * currently. To make this less problematic, let's shorten the
2640 * stop timeout for sessions, so that we don't wait
2641 * forever. */
2642
2643 /* Make sure that the session shells are terminated with
2644 * SIGHUP since bash and friends tend to ignore SIGTERM */
2645 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2646 if (r < 0)
2647 return r;
2648
2649 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2650 if (r < 0)
2651 return r;
2652
2653 r = sd_bus_message_close_container(m);
2654 if (r < 0)
2655 return r;
2656
2657 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2658 if (r < 0)
2659 return r;
2660
2661 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2662 if (r < 0)
2663 return r;
2664
2665 if (job) {
2666 const char *j;
2667 char *copy;
2668
2669 r = sd_bus_message_read(reply, "o", &j);
2670 if (r < 0)
2671 return r;
2672
2673 copy = strdup(j);
2674 if (!copy)
2675 return -ENOMEM;
2676
2677 *job = copy;
2678 }
2679
2680 return 1;
2681}
2682
2683int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2684 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2685 int r;
2686
2687 assert(manager);
2688 assert(unit);
2689
2690 r = sd_bus_call_method(
2691 manager->bus,
2692 "org.freedesktop.systemd1",
2693 "/org/freedesktop/systemd1",
2694 "org.freedesktop.systemd1.Manager",
2695 "StartUnit",
2696 error,
2697 &reply,
2698 "ss", unit, "fail");
2699 if (r < 0)
2700 return r;
2701
2702 if (job) {
2703 const char *j;
2704 char *copy;
2705
2706 r = sd_bus_message_read(reply, "o", &j);
2707 if (r < 0)
2708 return r;
2709
2710 copy = strdup(j);
2711 if (!copy)
2712 return -ENOMEM;
2713
2714 *job = copy;
2715 }
2716
2717 return 1;
2718}
2719
2720int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2721 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2722 int r;
2723
2724 assert(manager);
2725 assert(unit);
2726
2727 r = sd_bus_call_method(
2728 manager->bus,
2729 "org.freedesktop.systemd1",
2730 "/org/freedesktop/systemd1",
2731 "org.freedesktop.systemd1.Manager",
2732 "StopUnit",
2733 error,
2734 &reply,
2735 "ss", unit, "fail");
2736 if (r < 0) {
2737 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2738 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2739
2740 if (job)
2741 *job = NULL;
2742
2743 sd_bus_error_free(error);
2744 return 0;
2745 }
2746
2747 return r;
2748 }
2749
2750 if (job) {
2751 const char *j;
2752 char *copy;
2753
2754 r = sd_bus_message_read(reply, "o", &j);
2755 if (r < 0)
2756 return r;
2757
2758 copy = strdup(j);
2759 if (!copy)
2760 return -ENOMEM;
2761
2762 *job = copy;
2763 }
2764
2765 return 1;
2766}
2767
2768int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2769 _cleanup_free_ char *path = NULL;
2770 int r;
2771
2772 assert(manager);
2773 assert(scope);
2774
2775 path = unit_dbus_path_from_name(scope);
2776 if (!path)
2777 return -ENOMEM;
2778
2779 r = sd_bus_call_method(
2780 manager->bus,
2781 "org.freedesktop.systemd1",
2782 path,
2783 "org.freedesktop.systemd1.Scope",
2784 "Abandon",
2785 error,
2786 NULL,
2787 NULL);
2788 if (r < 0) {
2789 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2790 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2791 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2792 sd_bus_error_free(error);
2793 return 0;
2794 }
2795
2796 return r;
2797 }
2798
2799 return 1;
2800}
2801
2802int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2803 assert(manager);
2804 assert(unit);
2805
2806 return sd_bus_call_method(
2807 manager->bus,
2808 "org.freedesktop.systemd1",
2809 "/org/freedesktop/systemd1",
2810 "org.freedesktop.systemd1.Manager",
2811 "KillUnit",
2812 error,
2813 NULL,
2814 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2815}
2816
2817int manager_unit_is_active(Manager *manager, const char *unit) {
2818 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2819 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2820 _cleanup_free_ char *path = NULL;
2821 const char *state;
2822 int r;
2823
2824 assert(manager);
2825 assert(unit);
2826
2827 path = unit_dbus_path_from_name(unit);
2828 if (!path)
2829 return -ENOMEM;
2830
2831 r = sd_bus_get_property(
2832 manager->bus,
2833 "org.freedesktop.systemd1",
2834 path,
2835 "org.freedesktop.systemd1.Unit",
2836 "ActiveState",
2837 &error,
2838 &reply,
2839 "s");
2840 if (r < 0) {
2841 /* systemd might have droppped off momentarily, let's
2842 * not make this an error */
2843 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2844 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2845 return true;
2846
2847 /* If the unit is already unloaded then it's not
2848 * active */
2849 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2850 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2851 return false;
2852
2853 return r;
2854 }
2855
2856 r = sd_bus_message_read(reply, "s", &state);
2857 if (r < 0)
2858 return -EINVAL;
2859
2860 return !streq(state, "inactive") && !streq(state, "failed");
2861}
2862
2863int manager_job_is_active(Manager *manager, const char *path) {
2864 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2865 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2866 int r;
2867
2868 assert(manager);
2869 assert(path);
2870
2871 r = sd_bus_get_property(
2872 manager->bus,
2873 "org.freedesktop.systemd1",
2874 path,
2875 "org.freedesktop.systemd1.Job",
2876 "State",
2877 &error,
2878 &reply,
2879 "s");
2880 if (r < 0) {
2881 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2882 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2883 return true;
2884
2885 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2886 return false;
2887
2888 return r;
2889 }
2890
2891 /* We don't actually care about the state really. The fact
2892 * that we could read the job state is enough for us */
2893
2894 return true;
2895}