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