]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-dbus.c
Merge pull request #561 from cmacq2/html-man-fixes
[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 r = manager_get_session_by_pid(m, leader, NULL);
693 if (r > 0)
694 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
695
696 /*
697 * Old gdm and lightdm start the user-session on the same VT as
698 * the greeter session. But they destroy the greeter session
699 * after the user-session and want the user-session to take
700 * over the VT. We need to support this for
701 * backwards-compatibility, so make sure we allow new sessions
702 * on a VT that a greeter is running on. Furthermore, to allow
703 * re-logins, we have to allow a greeter to take over a used VT for
704 * the exact same reasons.
705 */
706 if (c != SESSION_GREETER &&
707 vtnr > 0 &&
708 vtnr < m->seat0->position_count &&
709 m->seat0->positions[vtnr] &&
710 m->seat0->positions[vtnr]->class != SESSION_GREETER)
711 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
712
713 audit_session_from_pid(leader, &audit_id);
714 if (audit_id > 0) {
715 /* Keep our session IDs and the audit session IDs in sync */
716
717 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
718 return -ENOMEM;
719
720 /* Wut? There's already a session by this name and we
721 * didn't find it above? Weird, then let's not trust
722 * the audit data and let's better register a new
723 * ID */
724 if (hashmap_get(m->sessions, id)) {
725 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
726 audit_id = 0;
727
728 free(id);
729 id = NULL;
730 }
731 }
732
733 if (!id) {
734 do {
735 free(id);
736 id = NULL;
737
738 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
739 return -ENOMEM;
740
741 } while (hashmap_get(m->sessions, id));
742 }
743
744 r = manager_add_user_by_uid(m, uid, &user);
745 if (r < 0)
746 goto fail;
747
748 r = manager_add_session(m, id, &session);
749 if (r < 0)
750 goto fail;
751
752 session_set_user(session, user);
753
754 session->leader = leader;
755 session->audit_id = audit_id;
756 session->type = t;
757 session->class = c;
758 session->remote = remote;
759 session->vtnr = vtnr;
760
761 if (!isempty(tty)) {
762 session->tty = strdup(tty);
763 if (!session->tty) {
764 r = -ENOMEM;
765 goto fail;
766 }
767 }
768
769 if (!isempty(display)) {
770 session->display = strdup(display);
771 if (!session->display) {
772 r = -ENOMEM;
773 goto fail;
774 }
775 }
776
777 if (!isempty(remote_user)) {
778 session->remote_user = strdup(remote_user);
779 if (!session->remote_user) {
780 r = -ENOMEM;
781 goto fail;
782 }
783 }
784
785 if (!isempty(remote_host)) {
786 session->remote_host = strdup(remote_host);
787 if (!session->remote_host) {
788 r = -ENOMEM;
789 goto fail;
790 }
791 }
792
793 if (!isempty(service)) {
794 session->service = strdup(service);
795 if (!session->service) {
796 r = -ENOMEM;
797 goto fail;
798 }
799 }
800
801 if (!isempty(desktop)) {
802 session->desktop = strdup(desktop);
803 if (!session->desktop) {
804 r = -ENOMEM;
805 goto fail;
806 }
807 }
808
809 if (seat) {
810 r = seat_attach_session(seat, session);
811 if (r < 0)
812 goto fail;
813 }
814
815 r = session_start(session);
816 if (r < 0)
817 goto fail;
818
819 session->create_message = sd_bus_message_ref(message);
820
821 /* Now, let's wait until the slice unit and stuff got
822 * created. We send the reply back from
823 * session_send_create_reply(). */
824
825 return 1;
826
827 fail:
828 if (session)
829 session_add_to_gc_queue(session);
830
831 if (user)
832 user_add_to_gc_queue(user);
833
834 return r;
835 }
836
837 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
838 Manager *m = userdata;
839 Session *session;
840 const char *name;
841 int r;
842
843 assert(message);
844 assert(m);
845
846 r = sd_bus_message_read(message, "s", &name);
847 if (r < 0)
848 return r;
849
850 r = manager_get_session_from_creds(m, message, name, error, &session);
851 if (r < 0)
852 return r;
853
854 r = session_release(session);
855 if (r < 0)
856 return r;
857
858 return sd_bus_reply_method_return(message, NULL);
859 }
860
861 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
862 Manager *m = userdata;
863 Session *session;
864 const char *name;
865 int r;
866
867 assert(message);
868 assert(m);
869
870 r = sd_bus_message_read(message, "s", &name);
871 if (r < 0)
872 return r;
873
874 r = manager_get_session_from_creds(m, message, name, error, &session);
875 if (r < 0)
876 return r;
877
878 return bus_session_method_activate(message, session, error);
879 }
880
881 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
882 const char *session_name, *seat_name;
883 Manager *m = userdata;
884 Session *session;
885 Seat *seat;
886 int r;
887
888 assert(message);
889 assert(m);
890
891 /* Same as ActivateSession() but refuses to work if
892 * the seat doesn't match */
893
894 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
895 if (r < 0)
896 return r;
897
898 r = manager_get_session_from_creds(m, message, session_name, error, &session);
899 if (r < 0)
900 return r;
901
902 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
903 if (r < 0)
904 return r;
905
906 if (session->seat != seat)
907 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
908
909 r = session_activate(session);
910 if (r < 0)
911 return r;
912
913 return sd_bus_reply_method_return(message, NULL);
914 }
915
916 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
917 Manager *m = userdata;
918 Session *session;
919 const char *name;
920 int r;
921
922 assert(message);
923 assert(m);
924
925 r = sd_bus_message_read(message, "s", &name);
926 if (r < 0)
927 return r;
928
929 r = manager_get_session_from_creds(m, message, name, error, &session);
930 if (r < 0)
931 return r;
932
933 return bus_session_method_lock(message, session, error);
934 }
935
936 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
937 Manager *m = userdata;
938 int r;
939
940 assert(message);
941 assert(m);
942
943 r = bus_verify_polkit_async(
944 message,
945 CAP_SYS_ADMIN,
946 "org.freedesktop.login1.lock-sessions",
947 false,
948 UID_INVALID,
949 &m->polkit_registry,
950 error);
951 if (r < 0)
952 return r;
953 if (r == 0)
954 return 1; /* Will call us back */
955
956 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
957 if (r < 0)
958 return r;
959
960 return sd_bus_reply_method_return(message, NULL);
961 }
962
963 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
964 const char *name;
965 Manager *m = userdata;
966 Session *session;
967 int r;
968
969 assert(message);
970 assert(m);
971
972 r = sd_bus_message_read(message, "s", &name);
973 if (r < 0)
974 return r;
975
976 r = manager_get_session_from_creds(m, message, name, error, &session);
977 if (r < 0)
978 return r;
979
980 return bus_session_method_kill(message, session, error);
981 }
982
983 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
984 Manager *m = userdata;
985 uint32_t uid;
986 User *user;
987 int r;
988
989 assert(message);
990 assert(m);
991
992 r = sd_bus_message_read(message, "u", &uid);
993 if (r < 0)
994 return r;
995
996 r = manager_get_user_from_creds(m, message, uid, error, &user);
997 if (r < 0)
998 return r;
999
1000 return bus_user_method_kill(message, user, error);
1001 }
1002
1003 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1004 Manager *m = userdata;
1005 const char *name;
1006 Session *session;
1007 int r;
1008
1009 assert(message);
1010 assert(m);
1011
1012 r = sd_bus_message_read(message, "s", &name);
1013 if (r < 0)
1014 return r;
1015
1016 r = manager_get_session_from_creds(m, message, name, error, &session);
1017 if (r < 0)
1018 return r;
1019
1020 return bus_session_method_terminate(message, session, error);
1021 }
1022
1023 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1024 Manager *m = userdata;
1025 uint32_t uid;
1026 User *user;
1027 int r;
1028
1029 assert(message);
1030 assert(m);
1031
1032 r = sd_bus_message_read(message, "u", &uid);
1033 if (r < 0)
1034 return r;
1035
1036 r = manager_get_user_from_creds(m, message, uid, error, &user);
1037 if (r < 0)
1038 return r;
1039
1040 return bus_user_method_terminate(message, user, error);
1041 }
1042
1043 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1044 Manager *m = userdata;
1045 const char *name;
1046 Seat *seat;
1047 int r;
1048
1049 assert(message);
1050 assert(m);
1051
1052 r = sd_bus_message_read(message, "s", &name);
1053 if (r < 0)
1054 return r;
1055
1056 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1057 if (r < 0)
1058 return r;
1059
1060 return bus_seat_method_terminate(message, seat, error);
1061 }
1062
1063 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1064 _cleanup_free_ char *cc = NULL;
1065 Manager *m = userdata;
1066 int b, r;
1067 struct passwd *pw;
1068 const char *path;
1069 uint32_t uid;
1070 int interactive;
1071
1072 assert(message);
1073 assert(m);
1074
1075 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1076 if (r < 0)
1077 return r;
1078
1079 if (uid == UID_INVALID) {
1080 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1081
1082 /* Note that we get the owner UID of the session, not the actual client UID here! */
1083 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1084 if (r < 0)
1085 return r;
1086
1087 r = sd_bus_creds_get_owner_uid(creds, &uid);
1088 if (r < 0)
1089 return r;
1090 }
1091
1092 errno = 0;
1093 pw = getpwuid(uid);
1094 if (!pw)
1095 return errno ? -errno : -ENOENT;
1096
1097 r = bus_verify_polkit_async(
1098 message,
1099 CAP_SYS_ADMIN,
1100 "org.freedesktop.login1.set-user-linger",
1101 interactive,
1102 UID_INVALID,
1103 &m->polkit_registry,
1104 error);
1105 if (r < 0)
1106 return r;
1107 if (r == 0)
1108 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1109
1110 mkdir_p_label("/var/lib/systemd", 0755);
1111
1112 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1113 if (r < 0)
1114 return r;
1115
1116 cc = cescape(pw->pw_name);
1117 if (!cc)
1118 return -ENOMEM;
1119
1120 path = strjoina("/var/lib/systemd/linger/", cc);
1121 if (b) {
1122 User *u;
1123
1124 r = touch(path);
1125 if (r < 0)
1126 return r;
1127
1128 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1129 user_start(u);
1130
1131 } else {
1132 User *u;
1133
1134 r = unlink(path);
1135 if (r < 0 && errno != ENOENT)
1136 return -errno;
1137
1138 u = hashmap_get(m->users, UID_TO_PTR(uid));
1139 if (u)
1140 user_add_to_gc_queue(u);
1141 }
1142
1143 return sd_bus_reply_method_return(message, NULL);
1144 }
1145
1146 static int trigger_device(Manager *m, struct udev_device *d) {
1147 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1148 struct udev_list_entry *first, *item;
1149 int r;
1150
1151 assert(m);
1152
1153 e = udev_enumerate_new(m->udev);
1154 if (!e)
1155 return -ENOMEM;
1156
1157 if (d) {
1158 r = udev_enumerate_add_match_parent(e, d);
1159 if (r < 0)
1160 return r;
1161 }
1162
1163 r = udev_enumerate_scan_devices(e);
1164 if (r < 0)
1165 return r;
1166
1167 first = udev_enumerate_get_list_entry(e);
1168 udev_list_entry_foreach(item, first) {
1169 _cleanup_free_ char *t = NULL;
1170 const char *p;
1171
1172 p = udev_list_entry_get_name(item);
1173
1174 t = strappend(p, "/uevent");
1175 if (!t)
1176 return -ENOMEM;
1177
1178 write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
1179 }
1180
1181 return 0;
1182 }
1183
1184 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1185 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1186 _cleanup_free_ char *rule = NULL, *file = NULL;
1187 const char *id_for_seat;
1188 int r;
1189
1190 assert(m);
1191 assert(seat);
1192 assert(sysfs);
1193
1194 d = udev_device_new_from_syspath(m->udev, sysfs);
1195 if (!d)
1196 return -ENODEV;
1197
1198 if (!udev_device_has_tag(d, "seat"))
1199 return -ENODEV;
1200
1201 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1202 if (!id_for_seat)
1203 return -ENODEV;
1204
1205 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1206 return -ENOMEM;
1207
1208 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1209 return -ENOMEM;
1210
1211 mkdir_p_label("/etc/udev/rules.d", 0755);
1212 mac_selinux_init("/etc");
1213 r = write_string_file_atomic_label(file, rule);
1214 if (r < 0)
1215 return r;
1216
1217 return trigger_device(m, d);
1218 }
1219
1220 static int flush_devices(Manager *m) {
1221 _cleanup_closedir_ DIR *d;
1222
1223 assert(m);
1224
1225 d = opendir("/etc/udev/rules.d");
1226 if (!d) {
1227 if (errno != ENOENT)
1228 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1229 } else {
1230 struct dirent *de;
1231
1232 while ((de = readdir(d))) {
1233
1234 if (!dirent_is_file(de))
1235 continue;
1236
1237 if (!startswith(de->d_name, "72-seat-"))
1238 continue;
1239
1240 if (!endswith(de->d_name, ".rules"))
1241 continue;
1242
1243 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1244 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1245 }
1246 }
1247
1248 return trigger_device(m, NULL);
1249 }
1250
1251 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1252 const char *sysfs, *seat;
1253 Manager *m = userdata;
1254 int interactive, r;
1255
1256 assert(message);
1257 assert(m);
1258
1259 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1260 if (r < 0)
1261 return r;
1262
1263 if (!path_startswith(sysfs, "/sys"))
1264 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1265
1266 if (!seat_name_is_valid(seat))
1267 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1268
1269 r = bus_verify_polkit_async(
1270 message,
1271 CAP_SYS_ADMIN,
1272 "org.freedesktop.login1.attach-device",
1273 interactive,
1274 UID_INVALID,
1275 &m->polkit_registry,
1276 error);
1277 if (r < 0)
1278 return r;
1279 if (r == 0)
1280 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1281
1282 r = attach_device(m, seat, sysfs);
1283 if (r < 0)
1284 return r;
1285
1286 return sd_bus_reply_method_return(message, NULL);
1287 }
1288
1289 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1290 Manager *m = userdata;
1291 int interactive, r;
1292
1293 assert(message);
1294 assert(m);
1295
1296 r = sd_bus_message_read(message, "b", &interactive);
1297 if (r < 0)
1298 return r;
1299
1300 r = bus_verify_polkit_async(
1301 message,
1302 CAP_SYS_ADMIN,
1303 "org.freedesktop.login1.flush-devices",
1304 interactive,
1305 UID_INVALID,
1306 &m->polkit_registry,
1307 error);
1308 if (r < 0)
1309 return r;
1310 if (r == 0)
1311 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1312
1313 r = flush_devices(m);
1314 if (r < 0)
1315 return r;
1316
1317 return sd_bus_reply_method_return(message, NULL);
1318 }
1319
1320 static int have_multiple_sessions(
1321 Manager *m,
1322 uid_t uid) {
1323
1324 Session *session;
1325 Iterator i;
1326
1327 assert(m);
1328
1329 /* Check for other users' sessions. Greeter sessions do not
1330 * count, and non-login sessions do not count either. */
1331 HASHMAP_FOREACH(session, m->sessions, i)
1332 if (session->class == SESSION_USER &&
1333 session->user->uid != uid)
1334 return true;
1335
1336 return false;
1337 }
1338
1339 static int bus_manager_log_shutdown(
1340 Manager *m,
1341 InhibitWhat w,
1342 const char *unit_name) {
1343
1344 const char *p, *q;
1345
1346 assert(m);
1347 assert(unit_name);
1348
1349 if (w != INHIBIT_SHUTDOWN)
1350 return 0;
1351
1352 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1353 p = "MESSAGE=System is powering down.";
1354 q = "SHUTDOWN=power-off";
1355 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1356 p = "MESSAGE=System is halting.";
1357 q = "SHUTDOWN=halt";
1358 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1359 p = "MESSAGE=System is rebooting.";
1360 q = "SHUTDOWN=reboot";
1361 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1362 p = "MESSAGE=System is rebooting with kexec.";
1363 q = "SHUTDOWN=kexec";
1364 } else {
1365 p = "MESSAGE=System is shutting down.";
1366 q = NULL;
1367 }
1368
1369 return log_struct(LOG_NOTICE,
1370 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1371 p,
1372 q,
1373 NULL);
1374 }
1375
1376 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1377 Manager *m = userdata;
1378
1379 assert(e);
1380 assert(m);
1381
1382 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1383 return 0;
1384 }
1385
1386 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1387 int r;
1388
1389 assert(m);
1390
1391 if (until <= now(CLOCK_MONOTONIC))
1392 return 0;
1393
1394 /* We want to ignore the lid switch for a while after each
1395 * suspend, and after boot-up. Hence let's install a timer for
1396 * this. As long as the event source exists we ignore the lid
1397 * switch. */
1398
1399 if (m->lid_switch_ignore_event_source) {
1400 usec_t u;
1401
1402 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1403 if (r < 0)
1404 return r;
1405
1406 if (until <= u)
1407 return 0;
1408
1409 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1410 } else
1411 r = sd_event_add_time(
1412 m->event,
1413 &m->lid_switch_ignore_event_source,
1414 CLOCK_MONOTONIC,
1415 until, 0,
1416 lid_switch_ignore_handler, m);
1417
1418 return r;
1419 }
1420
1421 static int execute_shutdown_or_sleep(
1422 Manager *m,
1423 InhibitWhat w,
1424 const char *unit_name,
1425 sd_bus_error *error) {
1426
1427 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1428 const char *p;
1429 char *c;
1430 int r;
1431
1432 assert(m);
1433 assert(w >= 0);
1434 assert(w < _INHIBIT_WHAT_MAX);
1435 assert(unit_name);
1436
1437 bus_manager_log_shutdown(m, w, unit_name);
1438
1439 r = sd_bus_call_method(
1440 m->bus,
1441 "org.freedesktop.systemd1",
1442 "/org/freedesktop/systemd1",
1443 "org.freedesktop.systemd1.Manager",
1444 "StartUnit",
1445 error,
1446 &reply,
1447 "ss", unit_name, "replace-irreversibly");
1448 if (r < 0)
1449 return r;
1450
1451 r = sd_bus_message_read(reply, "o", &p);
1452 if (r < 0)
1453 return r;
1454
1455 c = strdup(p);
1456 if (!c)
1457 return -ENOMEM;
1458
1459 m->action_unit = unit_name;
1460 free(m->action_job);
1461 m->action_job = c;
1462 m->action_what = w;
1463
1464 /* Make sure the lid switch is ignored for a while */
1465 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1466
1467 return 0;
1468 }
1469
1470 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1471
1472 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1473 Inhibitor *offending = NULL;
1474 int r;
1475
1476 assert(manager);
1477
1478 if (manager->action_what == 0 || manager->action_job)
1479 return 0;
1480
1481 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1482 _cleanup_free_ char *comm = NULL, *u = NULL;
1483
1484 if (!timeout)
1485 return 0;
1486
1487 (void) get_process_comm(offending->pid, &comm);
1488 u = uid_to_name(offending->uid);
1489
1490 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1491 offending->uid, strna(u),
1492 offending->pid, strna(comm));
1493 }
1494
1495 /* Actually do the operation */
1496 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1497 if (r < 0) {
1498 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1499
1500 manager->action_unit = NULL;
1501 manager->action_what = 0;
1502 return r;
1503 }
1504
1505 return 1;
1506 }
1507
1508 static int manager_inhibit_timeout_handler(
1509 sd_event_source *s,
1510 uint64_t usec,
1511 void *userdata) {
1512
1513 Manager *manager = userdata;
1514 int r;
1515
1516 assert(manager);
1517 assert(manager->inhibit_timeout_source == s);
1518
1519 r = manager_dispatch_delayed(manager, true);
1520 return (r < 0) ? r : 0;
1521 }
1522
1523 static int delay_shutdown_or_sleep(
1524 Manager *m,
1525 InhibitWhat w,
1526 const char *unit_name) {
1527
1528 int r;
1529 usec_t timeout_val;
1530
1531 assert(m);
1532 assert(w >= 0);
1533 assert(w < _INHIBIT_WHAT_MAX);
1534 assert(unit_name);
1535
1536 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1537
1538 if (m->inhibit_timeout_source) {
1539 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1540 if (r < 0)
1541 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1542
1543 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1544 if (r < 0)
1545 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1546 } else {
1547 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1548 timeout_val, 0, manager_inhibit_timeout_handler, m);
1549 if (r < 0)
1550 return r;
1551 }
1552
1553 m->action_unit = unit_name;
1554 m->action_what = w;
1555
1556 return 0;
1557 }
1558
1559 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1560
1561 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1562 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1563 [INHIBIT_SLEEP] = "PrepareForSleep"
1564 };
1565
1566 int active = _active;
1567
1568 assert(m);
1569 assert(w >= 0);
1570 assert(w < _INHIBIT_WHAT_MAX);
1571 assert(signal_name[w]);
1572
1573 return sd_bus_emit_signal(m->bus,
1574 "/org/freedesktop/login1",
1575 "org.freedesktop.login1.Manager",
1576 signal_name[w],
1577 "b",
1578 active);
1579 }
1580
1581 int bus_manager_shutdown_or_sleep_now_or_later(
1582 Manager *m,
1583 const char *unit_name,
1584 InhibitWhat w,
1585 sd_bus_error *error) {
1586
1587 bool delayed;
1588 int r;
1589
1590 assert(m);
1591 assert(unit_name);
1592 assert(w >= 0);
1593 assert(w <= _INHIBIT_WHAT_MAX);
1594 assert(!m->action_job);
1595
1596 /* Tell everybody to prepare for shutdown/sleep */
1597 send_prepare_for(m, w, true);
1598
1599 delayed =
1600 m->inhibit_delay_max > 0 &&
1601 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1602
1603 if (delayed)
1604 /* Shutdown is delayed, keep in mind what we
1605 * want to do, and start a timeout */
1606 r = delay_shutdown_or_sleep(m, w, unit_name);
1607 else
1608 /* Shutdown is not delayed, execute it
1609 * immediately */
1610 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1611
1612 return r;
1613 }
1614
1615 static int verify_shutdown_creds(
1616 Manager *m,
1617 sd_bus_message *message,
1618 InhibitWhat w,
1619 bool interactive,
1620 const char *action,
1621 const char *action_multiple_sessions,
1622 const char *action_ignore_inhibit,
1623 sd_bus_error *error) {
1624
1625 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1626 bool multiple_sessions, blocked;
1627 uid_t uid;
1628 int r;
1629
1630 assert(m);
1631 assert(message);
1632 assert(w >= 0);
1633 assert(w <= _INHIBIT_WHAT_MAX);
1634
1635 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1636 if (r < 0)
1637 return r;
1638
1639 r = sd_bus_creds_get_euid(creds, &uid);
1640 if (r < 0)
1641 return r;
1642
1643 r = have_multiple_sessions(m, uid);
1644 if (r < 0)
1645 return r;
1646
1647 multiple_sessions = r > 0;
1648 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1649
1650 if (multiple_sessions && action_multiple_sessions) {
1651 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
1652 if (r < 0)
1653 return r;
1654 if (r == 0)
1655 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1656 }
1657
1658 if (blocked && action_ignore_inhibit) {
1659 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
1660 if (r < 0)
1661 return r;
1662 if (r == 0)
1663 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1664 }
1665
1666 if (!multiple_sessions && !blocked && action) {
1667 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
1668 if (r < 0)
1669 return r;
1670 if (r == 0)
1671 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1672 }
1673
1674 return 0;
1675 }
1676
1677 static int method_do_shutdown_or_sleep(
1678 Manager *m,
1679 sd_bus_message *message,
1680 const char *unit_name,
1681 InhibitWhat w,
1682 const char *action,
1683 const char *action_multiple_sessions,
1684 const char *action_ignore_inhibit,
1685 const char *sleep_verb,
1686 sd_bus_error *error) {
1687
1688 int interactive, r;
1689
1690 assert(m);
1691 assert(message);
1692 assert(unit_name);
1693 assert(w >= 0);
1694 assert(w <= _INHIBIT_WHAT_MAX);
1695
1696 r = sd_bus_message_read(message, "b", &interactive);
1697 if (r < 0)
1698 return r;
1699
1700 /* Don't allow multiple jobs being executed at the same time */
1701 if (m->action_what)
1702 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1703
1704 if (sleep_verb) {
1705 r = can_sleep(sleep_verb);
1706 if (r < 0)
1707 return r;
1708
1709 if (r == 0)
1710 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1711 }
1712
1713 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1714 action_ignore_inhibit, error);
1715 if (r != 0)
1716 return r;
1717
1718 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1719 if (r < 0)
1720 return r;
1721
1722 return sd_bus_reply_method_return(message, NULL);
1723 }
1724
1725 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1726 Manager *m = userdata;
1727
1728 return method_do_shutdown_or_sleep(
1729 m, message,
1730 SPECIAL_POWEROFF_TARGET,
1731 INHIBIT_SHUTDOWN,
1732 "org.freedesktop.login1.power-off",
1733 "org.freedesktop.login1.power-off-multiple-sessions",
1734 "org.freedesktop.login1.power-off-ignore-inhibit",
1735 NULL,
1736 error);
1737 }
1738
1739 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1740 Manager *m = userdata;
1741
1742 return method_do_shutdown_or_sleep(
1743 m, message,
1744 SPECIAL_REBOOT_TARGET,
1745 INHIBIT_SHUTDOWN,
1746 "org.freedesktop.login1.reboot",
1747 "org.freedesktop.login1.reboot-multiple-sessions",
1748 "org.freedesktop.login1.reboot-ignore-inhibit",
1749 NULL,
1750 error);
1751 }
1752
1753 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1754 Manager *m = userdata;
1755
1756 return method_do_shutdown_or_sleep(
1757 m, message,
1758 SPECIAL_SUSPEND_TARGET,
1759 INHIBIT_SLEEP,
1760 "org.freedesktop.login1.suspend",
1761 "org.freedesktop.login1.suspend-multiple-sessions",
1762 "org.freedesktop.login1.suspend-ignore-inhibit",
1763 "suspend",
1764 error);
1765 }
1766
1767 static int nologin_timeout_handler(
1768 sd_event_source *s,
1769 uint64_t usec,
1770 void *userdata) {
1771
1772 Manager *m = userdata;
1773 int r;
1774
1775 log_info("Creating /run/nologin, blocking further logins...");
1776
1777 r = write_string_file("/run/nologin", "System is going down.", WRITE_STRING_FILE_ATOMIC);
1778 if (r < 0)
1779 log_error_errno(r, "Failed to create /run/nologin: %m");
1780 else
1781 m->unlink_nologin = true;
1782
1783 return 0;
1784 }
1785
1786 static int update_schedule_file(Manager *m) {
1787
1788 int r;
1789 _cleanup_fclose_ FILE *f = NULL;
1790 _cleanup_free_ char *t = NULL, *temp_path = NULL;
1791
1792 assert(m);
1793
1794 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1795 if (r < 0)
1796 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1797
1798 t = cescape(m->wall_message);
1799 if (!t)
1800 return log_oom();
1801
1802 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1803 if (r < 0)
1804 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1805
1806 (void) fchmod(fileno(f), 0644);
1807
1808 fprintf(f,
1809 "USEC="USEC_FMT"\n"
1810 "WARN_WALL=%i\n"
1811 "MODE=%s\n",
1812 m->scheduled_shutdown_timeout,
1813 m->enable_wall_messages,
1814 m->scheduled_shutdown_type);
1815
1816 if (!isempty(m->wall_message))
1817 fprintf(f, "WALL_MESSAGE=%s\n", t);
1818
1819 (void) fflush_and_check(f);
1820
1821 if (ferror(f) || rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1822 log_error_errno(errno, "Failed to write information about scheduled shutdowns: %m");
1823 r = -errno;
1824
1825 (void) unlink(temp_path);
1826 (void) unlink("/run/systemd/shutdown/scheduled");
1827 }
1828
1829 return r;
1830 }
1831
1832 static int manager_scheduled_shutdown_handler(
1833 sd_event_source *s,
1834 uint64_t usec,
1835 void *userdata) {
1836
1837 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1838 Manager *m = userdata;
1839 const char *target;
1840 int r;
1841
1842 assert(m);
1843
1844 if (isempty(m->scheduled_shutdown_type))
1845 return 0;
1846
1847 if (streq(m->scheduled_shutdown_type, "halt"))
1848 target = SPECIAL_HALT_TARGET;
1849 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1850 target = SPECIAL_POWEROFF_TARGET;
1851 else
1852 target = SPECIAL_REBOOT_TARGET;
1853
1854 r = execute_shutdown_or_sleep(m, 0, target, &error);
1855 if (r < 0)
1856 return log_error_errno(r, "Unable to execute transition to %s: %m", target);
1857
1858 return 0;
1859 }
1860
1861 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1862 Manager *m = userdata;
1863 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1864 const char *action_multiple_sessions = NULL;
1865 const char *action_ignore_inhibit = NULL;
1866 const char *action = NULL;
1867 uint64_t elapse;
1868 char *type;
1869 int r;
1870
1871 assert(m);
1872 assert(message);
1873
1874 r = sd_bus_message_read(message, "st", &type, &elapse);
1875 if (r < 0)
1876 return r;
1877
1878 if (streq(type, "reboot")) {
1879 action = "org.freedesktop.login1.reboot";
1880 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1881 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1882 } else if (streq(type, "halt")) {
1883 action = "org.freedesktop.login1.halt";
1884 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1885 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1886 } else if (streq(type, "poweroff")) {
1887 action = "org.freedesktop.login1.poweroff";
1888 action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
1889 action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
1890 } else
1891 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1892
1893 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1894 action, action_multiple_sessions, action_ignore_inhibit, error);
1895 if (r != 0)
1896 return r;
1897
1898 if (m->scheduled_shutdown_timeout_source) {
1899 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1900 if (r < 0)
1901 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1902
1903 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
1904 if (r < 0)
1905 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1906 } else {
1907 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
1908 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
1909 if (r < 0)
1910 return log_error_errno(r, "sd_event_add_time() failed: %m");
1911 }
1912
1913 r = free_and_strdup(&m->scheduled_shutdown_type, type);
1914 if (r < 0) {
1915 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1916 return log_oom();
1917 }
1918
1919 if (m->nologin_timeout_source) {
1920 r = sd_event_source_set_time(m->nologin_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->nologin_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->nologin_timeout_source,
1929 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
1930 if (r < 0)
1931 return log_error_errno(r, "sd_event_add_time() failed: %m");
1932 }
1933
1934 m->scheduled_shutdown_timeout = elapse;
1935
1936 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1937 if (r >= 0) {
1938 const char *tty;
1939
1940 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
1941 (void) sd_bus_creds_get_tty(creds, &tty);
1942
1943 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
1944 if (r < 0) {
1945 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1946 return log_oom();
1947 }
1948 }
1949
1950 r = manager_setup_wall_message_timer(m);
1951 if (r < 0)
1952 return r;
1953
1954 if (!isempty(type)) {
1955 r = update_schedule_file(m);
1956 if (r < 0)
1957 return r;
1958 } else
1959 (void) unlink("/run/systemd/shutdown/scheduled");
1960
1961 return sd_bus_reply_method_return(message, NULL);
1962 }
1963
1964 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1965 Manager *m = userdata;
1966 bool cancelled;
1967
1968 assert(m);
1969 assert(message);
1970
1971 cancelled = m->scheduled_shutdown_type != NULL;
1972
1973 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1974 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
1975 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
1976 free(m->scheduled_shutdown_type);
1977 m->scheduled_shutdown_type = NULL;
1978 m->scheduled_shutdown_timeout = 0;
1979
1980 if (m->unlink_nologin) {
1981 (void) unlink("/run/nologin");
1982 m->unlink_nologin = false;
1983 }
1984
1985 if (cancelled) {
1986 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
1987 const char *tty = NULL;
1988 uid_t uid = 0;
1989 int r;
1990
1991 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
1992 if (r >= 0) {
1993 (void) sd_bus_creds_get_uid(creds, &uid);
1994 (void) sd_bus_creds_get_tty(creds, &tty);
1995 }
1996
1997 utmp_wall("The system shutdown has been cancelled",
1998 lookup_uid(uid), tty, logind_wall_tty_filter, m);
1999 }
2000
2001 return sd_bus_reply_method_return(message, "b", cancelled);
2002 }
2003
2004 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2005 Manager *m = userdata;
2006
2007 return method_do_shutdown_or_sleep(
2008 m, message,
2009 SPECIAL_HIBERNATE_TARGET,
2010 INHIBIT_SLEEP,
2011 "org.freedesktop.login1.hibernate",
2012 "org.freedesktop.login1.hibernate-multiple-sessions",
2013 "org.freedesktop.login1.hibernate-ignore-inhibit",
2014 "hibernate",
2015 error);
2016 }
2017
2018 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2019 Manager *m = userdata;
2020
2021 return method_do_shutdown_or_sleep(
2022 m, message,
2023 SPECIAL_HYBRID_SLEEP_TARGET,
2024 INHIBIT_SLEEP,
2025 "org.freedesktop.login1.hibernate",
2026 "org.freedesktop.login1.hibernate-multiple-sessions",
2027 "org.freedesktop.login1.hibernate-ignore-inhibit",
2028 "hybrid-sleep",
2029 error);
2030 }
2031
2032 static int method_can_shutdown_or_sleep(
2033 Manager *m,
2034 sd_bus_message *message,
2035 InhibitWhat w,
2036 const char *action,
2037 const char *action_multiple_sessions,
2038 const char *action_ignore_inhibit,
2039 const char *sleep_verb,
2040 sd_bus_error *error) {
2041
2042 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2043 bool multiple_sessions, challenge, blocked;
2044 const char *result = NULL;
2045 uid_t uid;
2046 int r;
2047
2048 assert(m);
2049 assert(message);
2050 assert(w >= 0);
2051 assert(w <= _INHIBIT_WHAT_MAX);
2052 assert(action);
2053 assert(action_multiple_sessions);
2054 assert(action_ignore_inhibit);
2055
2056 if (sleep_verb) {
2057 r = can_sleep(sleep_verb);
2058 if (r < 0)
2059 return r;
2060 if (r == 0)
2061 return sd_bus_reply_method_return(message, "s", "na");
2062 }
2063
2064 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2065 if (r < 0)
2066 return r;
2067
2068 r = sd_bus_creds_get_euid(creds, &uid);
2069 if (r < 0)
2070 return r;
2071
2072 r = have_multiple_sessions(m, uid);
2073 if (r < 0)
2074 return r;
2075
2076 multiple_sessions = r > 0;
2077 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2078
2079 if (multiple_sessions) {
2080 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
2081 if (r < 0)
2082 return r;
2083
2084 if (r > 0)
2085 result = "yes";
2086 else if (challenge)
2087 result = "challenge";
2088 else
2089 result = "no";
2090 }
2091
2092 if (blocked) {
2093 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
2094 if (r < 0)
2095 return r;
2096
2097 if (r > 0 && !result)
2098 result = "yes";
2099 else if (challenge && (!result || streq(result, "yes")))
2100 result = "challenge";
2101 else
2102 result = "no";
2103 }
2104
2105 if (!multiple_sessions && !blocked) {
2106 /* If neither inhibit nor multiple sessions
2107 * apply then just check the normal policy */
2108
2109 r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
2110 if (r < 0)
2111 return r;
2112
2113 if (r > 0)
2114 result = "yes";
2115 else if (challenge)
2116 result = "challenge";
2117 else
2118 result = "no";
2119 }
2120
2121 return sd_bus_reply_method_return(message, "s", result);
2122 }
2123
2124 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2125 Manager *m = userdata;
2126
2127 return method_can_shutdown_or_sleep(
2128 m, message,
2129 INHIBIT_SHUTDOWN,
2130 "org.freedesktop.login1.power-off",
2131 "org.freedesktop.login1.power-off-multiple-sessions",
2132 "org.freedesktop.login1.power-off-ignore-inhibit",
2133 NULL,
2134 error);
2135 }
2136
2137 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2138 Manager *m = userdata;
2139
2140 return method_can_shutdown_or_sleep(
2141 m, message,
2142 INHIBIT_SHUTDOWN,
2143 "org.freedesktop.login1.reboot",
2144 "org.freedesktop.login1.reboot-multiple-sessions",
2145 "org.freedesktop.login1.reboot-ignore-inhibit",
2146 NULL,
2147 error);
2148 }
2149
2150 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2151 Manager *m = userdata;
2152
2153 return method_can_shutdown_or_sleep(
2154 m, message,
2155 INHIBIT_SLEEP,
2156 "org.freedesktop.login1.suspend",
2157 "org.freedesktop.login1.suspend-multiple-sessions",
2158 "org.freedesktop.login1.suspend-ignore-inhibit",
2159 "suspend",
2160 error);
2161 }
2162
2163 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2164 Manager *m = userdata;
2165
2166 return method_can_shutdown_or_sleep(
2167 m, message,
2168 INHIBIT_SLEEP,
2169 "org.freedesktop.login1.hibernate",
2170 "org.freedesktop.login1.hibernate-multiple-sessions",
2171 "org.freedesktop.login1.hibernate-ignore-inhibit",
2172 "hibernate",
2173 error);
2174 }
2175
2176 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2177 Manager *m = userdata;
2178
2179 return method_can_shutdown_or_sleep(
2180 m, message,
2181 INHIBIT_SLEEP,
2182 "org.freedesktop.login1.hibernate",
2183 "org.freedesktop.login1.hibernate-multiple-sessions",
2184 "org.freedesktop.login1.hibernate-ignore-inhibit",
2185 "hybrid-sleep",
2186 error);
2187 }
2188
2189 static int property_get_reboot_to_firmware_setup(
2190 sd_bus *bus,
2191 const char *path,
2192 const char *interface,
2193 const char *property,
2194 sd_bus_message *reply,
2195 void *userdata,
2196 sd_bus_error *error) {
2197 int r;
2198
2199 assert(bus);
2200 assert(reply);
2201 assert(userdata);
2202
2203 r = efi_get_reboot_to_firmware();
2204 if (r < 0 && r != -EOPNOTSUPP)
2205 return r;
2206
2207 return sd_bus_message_append(reply, "b", r > 0);
2208 }
2209
2210 static int method_set_reboot_to_firmware_setup(
2211 sd_bus_message *message,
2212 void *userdata,
2213 sd_bus_error *error) {
2214
2215 int b, r;
2216 Manager *m = userdata;
2217
2218 assert(message);
2219 assert(m);
2220
2221 r = sd_bus_message_read(message, "b", &b);
2222 if (r < 0)
2223 return r;
2224
2225 r = bus_verify_polkit_async(message,
2226 CAP_SYS_ADMIN,
2227 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2228 false,
2229 UID_INVALID,
2230 &m->polkit_registry,
2231 error);
2232 if (r < 0)
2233 return r;
2234 if (r == 0)
2235 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2236
2237 r = efi_set_reboot_to_firmware(b);
2238 if (r < 0)
2239 return r;
2240
2241 return sd_bus_reply_method_return(message, NULL);
2242 }
2243
2244 static int method_can_reboot_to_firmware_setup(
2245 sd_bus_message *message,
2246 void *userdata,
2247 sd_bus_error *error) {
2248
2249 int r;
2250 bool challenge;
2251 const char *result;
2252 Manager *m = userdata;
2253
2254 assert(message);
2255 assert(m);
2256
2257 r = efi_reboot_to_firmware_supported();
2258 if (r == -EOPNOTSUPP)
2259 return sd_bus_reply_method_return(message, "s", "na");
2260 else if (r < 0)
2261 return r;
2262
2263 r = bus_test_polkit(message,
2264 CAP_SYS_ADMIN,
2265 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2266 UID_INVALID,
2267 &challenge,
2268 error);
2269 if (r < 0)
2270 return r;
2271
2272 if (r > 0)
2273 result = "yes";
2274 else if (challenge)
2275 result = "challenge";
2276 else
2277 result = "no";
2278
2279 return sd_bus_reply_method_return(message, "s", result);
2280 }
2281
2282 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2283 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
2284 const char *who, *why, *what, *mode;
2285 _cleanup_free_ char *id = NULL;
2286 _cleanup_close_ int fifo_fd = -1;
2287 Manager *m = userdata;
2288 Inhibitor *i = NULL;
2289 InhibitMode mm;
2290 InhibitWhat w;
2291 pid_t pid;
2292 uid_t uid;
2293 int r;
2294
2295 assert(message);
2296 assert(m);
2297
2298 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2299 if (r < 0)
2300 return r;
2301
2302 w = inhibit_what_from_string(what);
2303 if (w <= 0)
2304 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2305
2306 mm = inhibit_mode_from_string(mode);
2307 if (mm < 0)
2308 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2309
2310 /* Delay is only supported for shutdown/sleep */
2311 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2312 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2313
2314 /* Don't allow taking delay locks while we are already
2315 * executing the operation. We shouldn't create the impression
2316 * that the lock was successful if the machine is about to go
2317 * down/suspend any moment. */
2318 if (m->action_what & w)
2319 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2320
2321 r = bus_verify_polkit_async(
2322 message,
2323 CAP_SYS_BOOT,
2324 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2325 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2326 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2327 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2328 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2329 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2330 "org.freedesktop.login1.inhibit-handle-lid-switch",
2331 false,
2332 UID_INVALID,
2333 &m->polkit_registry,
2334 error);
2335 if (r < 0)
2336 return r;
2337 if (r == 0)
2338 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2339
2340 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2341 if (r < 0)
2342 return r;
2343
2344 r = sd_bus_creds_get_euid(creds, &uid);
2345 if (r < 0)
2346 return r;
2347
2348 r = sd_bus_creds_get_pid(creds, &pid);
2349 if (r < 0)
2350 return r;
2351
2352 do {
2353 free(id);
2354 id = NULL;
2355
2356 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2357 return -ENOMEM;
2358
2359 } while (hashmap_get(m->inhibitors, id));
2360
2361 r = manager_add_inhibitor(m, id, &i);
2362 if (r < 0)
2363 return r;
2364
2365 i->what = w;
2366 i->mode = mm;
2367 i->pid = pid;
2368 i->uid = uid;
2369 i->why = strdup(why);
2370 i->who = strdup(who);
2371
2372 if (!i->why || !i->who) {
2373 r = -ENOMEM;
2374 goto fail;
2375 }
2376
2377 fifo_fd = inhibitor_create_fifo(i);
2378 if (fifo_fd < 0) {
2379 r = fifo_fd;
2380 goto fail;
2381 }
2382
2383 inhibitor_start(i);
2384
2385 return sd_bus_reply_method_return(message, "h", fifo_fd);
2386
2387 fail:
2388 if (i)
2389 inhibitor_free(i);
2390
2391 return r;
2392 }
2393
2394 const sd_bus_vtable manager_vtable[] = {
2395 SD_BUS_VTABLE_START(0),
2396
2397 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2398 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2399
2400 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2401 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2402 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2403 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2404 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2405 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2406 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2407 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2408 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2409 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2410 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2411 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2412 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2413 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2414 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2415 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2416 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2417 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2418 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2419 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2420 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2421 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2422 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2423
2424 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2425 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2426 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2427 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2428 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2429 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2430 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2431 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2432 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2433 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2434 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2435 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2436 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2437 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2438 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2439 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2440 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2441 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2442 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2443 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2444 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2445 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2446 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2447 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2448 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2449 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2450 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2451 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2452 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2453 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2454 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2455 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2456 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2457 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2458 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2459 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2460 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2461 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2462 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2463 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2464
2465 SD_BUS_SIGNAL("SessionNew", "so", 0),
2466 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2467 SD_BUS_SIGNAL("UserNew", "uo", 0),
2468 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2469 SD_BUS_SIGNAL("SeatNew", "so", 0),
2470 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2471 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2472 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2473
2474 SD_BUS_VTABLE_END
2475 };
2476
2477 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2478 int r = 0;
2479
2480 assert(s);
2481 assert(unit);
2482
2483 if (!s->started)
2484 return r;
2485
2486 if (streq(result, "done"))
2487 r = session_send_create_reply(s, NULL);
2488 else {
2489 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
2490
2491 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2492 r = session_send_create_reply(s, &e);
2493 }
2494
2495 return r;
2496 }
2497
2498 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2499 const char *path, *result, *unit;
2500 Manager *m = userdata;
2501 Session *session;
2502 uint32_t id;
2503 User *user;
2504 int r;
2505
2506 assert(message);
2507 assert(m);
2508
2509 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2510 if (r < 0) {
2511 bus_log_parse_error(r);
2512 return r;
2513 }
2514
2515 if (m->action_job && streq(m->action_job, path)) {
2516 log_info("Operation finished.");
2517
2518 /* Tell people that they now may take a lock again */
2519 send_prepare_for(m, m->action_what, false);
2520
2521 free(m->action_job);
2522 m->action_job = NULL;
2523 m->action_unit = NULL;
2524 m->action_what = 0;
2525 return 0;
2526 }
2527
2528 session = hashmap_get(m->session_units, unit);
2529 if (session) {
2530
2531 if (streq_ptr(path, session->scope_job)) {
2532 free(session->scope_job);
2533 session->scope_job = NULL;
2534 }
2535
2536 session_jobs_reply(session, unit, result);
2537
2538 session_save(session);
2539 user_save(session->user);
2540 session_add_to_gc_queue(session);
2541 }
2542
2543 user = hashmap_get(m->user_units, unit);
2544 if (user) {
2545
2546 if (streq_ptr(path, user->service_job)) {
2547 free(user->service_job);
2548 user->service_job = NULL;
2549 }
2550
2551 if (streq_ptr(path, user->slice_job)) {
2552 free(user->slice_job);
2553 user->slice_job = NULL;
2554 }
2555
2556 LIST_FOREACH(sessions_by_user, session, user->sessions) {
2557 session_jobs_reply(session, unit, result);
2558 }
2559
2560 user_save(user);
2561 user_add_to_gc_queue(user);
2562 }
2563
2564 return 0;
2565 }
2566
2567 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2568 const char *path, *unit;
2569 Manager *m = userdata;
2570 Session *session;
2571 User *user;
2572 int r;
2573
2574 assert(message);
2575 assert(m);
2576
2577 r = sd_bus_message_read(message, "so", &unit, &path);
2578 if (r < 0) {
2579 bus_log_parse_error(r);
2580 return r;
2581 }
2582
2583 session = hashmap_get(m->session_units, unit);
2584 if (session)
2585 session_add_to_gc_queue(session);
2586
2587 user = hashmap_get(m->user_units, unit);
2588 if (user)
2589 user_add_to_gc_queue(user);
2590
2591 return 0;
2592 }
2593
2594 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2595 _cleanup_free_ char *unit = NULL;
2596 Manager *m = userdata;
2597 const char *path;
2598 Session *session;
2599 User *user;
2600 int r;
2601
2602 assert(message);
2603 assert(m);
2604
2605 path = sd_bus_message_get_path(message);
2606 if (!path)
2607 return 0;
2608
2609 r = unit_name_from_dbus_path(path, &unit);
2610 if (r == -EINVAL) /* not a unit */
2611 return 0;
2612 if (r < 0)
2613 return r;
2614
2615 session = hashmap_get(m->session_units, unit);
2616 if (session)
2617 session_add_to_gc_queue(session);
2618
2619 user = hashmap_get(m->user_units, unit);
2620 if (user)
2621 user_add_to_gc_queue(user);
2622
2623 return 0;
2624 }
2625
2626 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2627 Manager *m = userdata;
2628 Session *session;
2629 Iterator i;
2630 int b, r;
2631
2632 assert(message);
2633 assert(m);
2634
2635 r = sd_bus_message_read(message, "b", &b);
2636 if (r < 0) {
2637 bus_log_parse_error(r);
2638 return r;
2639 }
2640
2641 if (b)
2642 return 0;
2643
2644 /* systemd finished reloading, let's recheck all our sessions */
2645 log_debug("System manager has been reloaded, rechecking sessions...");
2646
2647 HASHMAP_FOREACH(session, m->sessions, i)
2648 session_add_to_gc_queue(session);
2649
2650 return 0;
2651 }
2652
2653 int match_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2654 const char *name, *old, *new;
2655 Manager *m = userdata;
2656 Session *session;
2657 Iterator i;
2658 int r;
2659 char *key;
2660
2661 assert(message);
2662 assert(m);
2663
2664 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2665 if (r < 0) {
2666 bus_log_parse_error(r);
2667 return r;
2668 }
2669
2670 if (isempty(old) || !isempty(new))
2671 return 0;
2672
2673 key = set_remove(m->busnames, (char*) old);
2674 if (!key)
2675 return 0;
2676
2677 /* Drop all controllers owned by this name */
2678
2679 free(key);
2680
2681 HASHMAP_FOREACH(session, m->sessions, i)
2682 if (session_is_controller(session, old))
2683 session_drop_controller(session);
2684
2685 return 0;
2686 }
2687
2688 int manager_send_changed(Manager *manager, const char *property, ...) {
2689 char **l;
2690
2691 assert(manager);
2692
2693 l = strv_from_stdarg_alloca(property);
2694
2695 return sd_bus_emit_properties_changed_strv(
2696 manager->bus,
2697 "/org/freedesktop/login1",
2698 "org.freedesktop.login1.Manager",
2699 l);
2700 }
2701
2702 int manager_start_scope(
2703 Manager *manager,
2704 const char *scope,
2705 pid_t pid,
2706 const char *slice,
2707 const char *description,
2708 const char *after, const char *after2,
2709 sd_bus_error *error,
2710 char **job) {
2711
2712 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2713 int r;
2714
2715 assert(manager);
2716 assert(scope);
2717 assert(pid > 1);
2718
2719 r = sd_bus_message_new_method_call(
2720 manager->bus,
2721 &m,
2722 "org.freedesktop.systemd1",
2723 "/org/freedesktop/systemd1",
2724 "org.freedesktop.systemd1.Manager",
2725 "StartTransientUnit");
2726 if (r < 0)
2727 return r;
2728
2729 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2730 if (r < 0)
2731 return r;
2732
2733 r = sd_bus_message_open_container(m, 'a', "(sv)");
2734 if (r < 0)
2735 return r;
2736
2737 if (!isempty(slice)) {
2738 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2739 if (r < 0)
2740 return r;
2741 }
2742
2743 if (!isempty(description)) {
2744 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2745 if (r < 0)
2746 return r;
2747 }
2748
2749 if (!isempty(after)) {
2750 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2751 if (r < 0)
2752 return r;
2753 }
2754
2755 if (!isempty(after2)) {
2756 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2757 if (r < 0)
2758 return r;
2759 }
2760
2761 /* cgroup empty notification is not available in containers
2762 * currently. To make this less problematic, let's shorten the
2763 * stop timeout for sessions, so that we don't wait
2764 * forever. */
2765
2766 /* Make sure that the session shells are terminated with
2767 * SIGHUP since bash and friends tend to ignore SIGTERM */
2768 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2769 if (r < 0)
2770 return r;
2771
2772 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2773 if (r < 0)
2774 return r;
2775
2776 r = sd_bus_message_close_container(m);
2777 if (r < 0)
2778 return r;
2779
2780 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2781 if (r < 0)
2782 return r;
2783
2784 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2785 if (r < 0)
2786 return r;
2787
2788 if (job) {
2789 const char *j;
2790 char *copy;
2791
2792 r = sd_bus_message_read(reply, "o", &j);
2793 if (r < 0)
2794 return r;
2795
2796 copy = strdup(j);
2797 if (!copy)
2798 return -ENOMEM;
2799
2800 *job = copy;
2801 }
2802
2803 return 1;
2804 }
2805
2806 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2807 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2808 int r;
2809
2810 assert(manager);
2811 assert(unit);
2812
2813 r = sd_bus_call_method(
2814 manager->bus,
2815 "org.freedesktop.systemd1",
2816 "/org/freedesktop/systemd1",
2817 "org.freedesktop.systemd1.Manager",
2818 "StartUnit",
2819 error,
2820 &reply,
2821 "ss", unit, "fail");
2822 if (r < 0)
2823 return r;
2824
2825 if (job) {
2826 const char *j;
2827 char *copy;
2828
2829 r = sd_bus_message_read(reply, "o", &j);
2830 if (r < 0)
2831 return r;
2832
2833 copy = strdup(j);
2834 if (!copy)
2835 return -ENOMEM;
2836
2837 *job = copy;
2838 }
2839
2840 return 1;
2841 }
2842
2843 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2844 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2845 int r;
2846
2847 assert(manager);
2848 assert(unit);
2849
2850 r = sd_bus_call_method(
2851 manager->bus,
2852 "org.freedesktop.systemd1",
2853 "/org/freedesktop/systemd1",
2854 "org.freedesktop.systemd1.Manager",
2855 "StopUnit",
2856 error,
2857 &reply,
2858 "ss", unit, "fail");
2859 if (r < 0) {
2860 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2861 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
2862
2863 if (job)
2864 *job = NULL;
2865
2866 sd_bus_error_free(error);
2867 return 0;
2868 }
2869
2870 return r;
2871 }
2872
2873 if (job) {
2874 const char *j;
2875 char *copy;
2876
2877 r = sd_bus_message_read(reply, "o", &j);
2878 if (r < 0)
2879 return r;
2880
2881 copy = strdup(j);
2882 if (!copy)
2883 return -ENOMEM;
2884
2885 *job = copy;
2886 }
2887
2888 return 1;
2889 }
2890
2891 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
2892 _cleanup_free_ char *path = NULL;
2893 int r;
2894
2895 assert(manager);
2896 assert(scope);
2897
2898 path = unit_dbus_path_from_name(scope);
2899 if (!path)
2900 return -ENOMEM;
2901
2902 r = sd_bus_call_method(
2903 manager->bus,
2904 "org.freedesktop.systemd1",
2905 path,
2906 "org.freedesktop.systemd1.Scope",
2907 "Abandon",
2908 error,
2909 NULL,
2910 NULL);
2911 if (r < 0) {
2912 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2913 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
2914 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
2915 sd_bus_error_free(error);
2916 return 0;
2917 }
2918
2919 return r;
2920 }
2921
2922 return 1;
2923 }
2924
2925 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
2926 assert(manager);
2927 assert(unit);
2928
2929 return sd_bus_call_method(
2930 manager->bus,
2931 "org.freedesktop.systemd1",
2932 "/org/freedesktop/systemd1",
2933 "org.freedesktop.systemd1.Manager",
2934 "KillUnit",
2935 error,
2936 NULL,
2937 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
2938 }
2939
2940 int manager_unit_is_active(Manager *manager, const char *unit) {
2941 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2942 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2943 _cleanup_free_ char *path = NULL;
2944 const char *state;
2945 int r;
2946
2947 assert(manager);
2948 assert(unit);
2949
2950 path = unit_dbus_path_from_name(unit);
2951 if (!path)
2952 return -ENOMEM;
2953
2954 r = sd_bus_get_property(
2955 manager->bus,
2956 "org.freedesktop.systemd1",
2957 path,
2958 "org.freedesktop.systemd1.Unit",
2959 "ActiveState",
2960 &error,
2961 &reply,
2962 "s");
2963 if (r < 0) {
2964 /* systemd might have droppped off momentarily, let's
2965 * not make this an error */
2966 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2967 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2968 return true;
2969
2970 /* If the unit is already unloaded then it's not
2971 * active */
2972 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2973 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
2974 return false;
2975
2976 return r;
2977 }
2978
2979 r = sd_bus_message_read(reply, "s", &state);
2980 if (r < 0)
2981 return -EINVAL;
2982
2983 return !streq(state, "inactive") && !streq(state, "failed");
2984 }
2985
2986 int manager_job_is_active(Manager *manager, const char *path) {
2987 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2988 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2989 int r;
2990
2991 assert(manager);
2992 assert(path);
2993
2994 r = sd_bus_get_property(
2995 manager->bus,
2996 "org.freedesktop.systemd1",
2997 path,
2998 "org.freedesktop.systemd1.Job",
2999 "State",
3000 &error,
3001 &reply,
3002 "s");
3003 if (r < 0) {
3004 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3005 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3006 return true;
3007
3008 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3009 return false;
3010
3011 return r;
3012 }
3013
3014 /* We don't actually care about the state really. The fact
3015 * that we could read the job state is enough for us */
3016
3017 return true;
3018 }