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