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