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