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