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