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