]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-dbus.c
bus: fix deserialization of polkit response
[thirdparty/systemd.git] / src / login / logind-dbus.c
CommitLineData
3f49d45a
LP
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
5430f7f2
LP
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
3f49d45a
LP
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
5430f7f2 16 Lesser General Public License for more details.
3f49d45a 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
3f49d45a
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
a185c5aa
LP
22#include <errno.h>
23#include <string.h>
98a28fef 24#include <unistd.h>
7f7bb946 25#include <pwd.h>
a185c5aa 26
cc377381
LP
27#include "sd-id128.h"
28#include "sd-messages.h"
98a28fef 29#include "strv.h"
49e942b2 30#include "mkdir.h"
9eb977db 31#include "path-util.h"
55af3897 32#include "special.h"
19adb8a3 33#include "sleep-config.h"
a5c32cff
HH
34#include "fileio-label.h"
35#include "label.h"
9444b1f2
LP
36#include "utf8.h"
37#include "unit-name.h"
fb6becb4 38#include "virt.h"
cc377381
LP
39#include "audit.h"
40#include "bus-util.h"
41#include "bus-error.h"
42#include "logind.h"
3f49d45a 43
cc377381
LP
44static int property_get_idle_hint(
45 sd_bus *bus,
46 const char *path,
47 const char *interface,
48 const char *property,
49 sd_bus_message *reply,
50 sd_bus_error *error,
51 void *userdata) {
a185c5aa 52
cc377381 53 Manager *m = userdata;
a185c5aa 54
cc377381
LP
55 assert(bus);
56 assert(reply);
57 assert(m);
58
59 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
a185c5aa
LP
60}
61
cc377381
LP
62static int property_get_idle_since_hint(
63 sd_bus *bus,
64 const char *path,
65 const char *interface,
66 const char *property,
67 sd_bus_message *reply,
68 sd_bus_error *error,
69 void *userdata) {
70
71 Manager *m = userdata;
a185c5aa 72 dual_timestamp t;
a185c5aa 73
cc377381
LP
74 assert(bus);
75 assert(reply);
a185c5aa
LP
76 assert(m);
77
78 manager_get_idle_hint(m, &t);
a185c5aa 79
cc377381 80 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
a185c5aa
LP
81}
82
cc377381
LP
83static int property_get_inhibited(
84 sd_bus *bus,
85 const char *path,
86 const char *interface,
87 const char *property,
88 sd_bus_message *reply,
89 sd_bus_error *error,
90 void *userdata) {
91
92 Manager *m = userdata;
f8e2fb7b 93 InhibitWhat w;
f8e2fb7b 94
cc377381
LP
95 assert(bus);
96 assert(reply);
97 assert(m);
f8e2fb7b 98
cc377381 99 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
f8e2fb7b 100
cc377381 101 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
f8e2fb7b
LP
102}
103
cc377381
LP
104static int property_get_preparing(
105 sd_bus *bus,
106 const char *path,
107 const char *interface,
108 const char *property,
109 sd_bus_message *reply,
110 sd_bus_error *error,
111 void *userdata) {
112
113 Manager *m = userdata;
114 bool b;
5e4a79da 115
cc377381
LP
116 assert(bus);
117 assert(reply);
118 assert(m);
5e4a79da
LP
119
120 if (streq(property, "PreparingForShutdown"))
314b4b0a 121 b = !!(m->action_what & INHIBIT_SHUTDOWN);
5e4a79da 122 else
314b4b0a 123 b = !!(m->action_what & INHIBIT_SLEEP);
5e4a79da 124
cc377381 125 return sd_bus_message_append(reply, "b", b);
5e4a79da
LP
126}
127
cc377381 128static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
fb6becb4 129
cc377381
LP
130static int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
131 _cleanup_free_ char *p = NULL;
132 Manager *m = userdata;
133 const char *name;
134 Session *session;
135 int r;
136
137 assert(bus);
138 assert(message);
139 assert(m);
140
141 r = sd_bus_message_read(message, "s", &name);
142 if (r < 0)
143 return sd_bus_reply_method_errno(bus, message, r, NULL);
144
145 session = hashmap_get(m->sessions, name);
146 if (!session)
147 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
148
149 p = session_bus_path(session);
150 if (!p)
151 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
152
153 return sd_bus_reply_method_return(bus, message, "o", p);
154}
155
156static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata) {
157 _cleanup_free_ char *p = NULL;
954449b8 158 Session *session = NULL;
cc377381
LP
159 Manager *m = userdata;
160 uint32_t pid;
161 int r;
162
163 assert(bus);
164 assert(message);
165 assert(m);
166
167 r = sd_bus_message_read(message, "u", &pid);
168 if (r < 0)
169 return sd_bus_reply_method_errno(bus, message, r, NULL);
170
171 r = manager_get_session_by_pid(m, pid, &session);
172 if (r < 0)
173 return sd_bus_reply_method_errno(bus, message, r, NULL);
174 if (!session)
175 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SESSION_FOR_PID, "PID %lu does not belong to any known session", (unsigned long) pid);
176
177 p = session_bus_path(session);
178 if (!p)
179 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
180
181 return sd_bus_reply_method_return(bus, message, "o", p);
182}
183
184static int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata) {
185 _cleanup_free_ char *p = NULL;
186 Manager *m = userdata;
187 uint32_t uid;
188 User *user;
189 int r;
190
191 assert(bus);
192 assert(message);
193 assert(m);
194
195 r = sd_bus_message_read(message, "u", &uid);
196 if (r < 0)
197 return sd_bus_reply_method_errno(bus, message, r, NULL);
198
199 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
200 if (!user)
201 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_USER, "No user '%lu' known or logged in", (unsigned long) uid);
202
203 p = user_bus_path(user);
204 if (!p)
205 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
206
207 return sd_bus_reply_method_return(bus, message, "o", p);
208}
209
210static int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata) {
211 _cleanup_free_ char *p = NULL;
212 Manager *m = userdata;
954449b8 213 User *user = NULL;
cc377381 214 uint32_t pid;
fb6becb4 215 int r;
98a28fef 216
cc377381
LP
217 assert(bus);
218 assert(message);
98a28fef 219 assert(m);
cc377381
LP
220
221 r = sd_bus_message_read(message, "u", &pid);
222 if (r < 0)
223 return sd_bus_reply_method_errno(bus, message, r, NULL);
224
225 r = manager_get_user_by_pid(m, pid, &user);
226 if (r < 0)
227 return sd_bus_reply_method_errno(bus, message, r, NULL);
228 if (!user)
229 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_USER_FOR_PID, "PID %lu does not belong to any known or logged in user", (unsigned long) pid);
230
231 p = user_bus_path(user);
232 if (!p)
233 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
234
235 return sd_bus_reply_method_return(bus, message, "o", p);
236}
237
238static int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata) {
239 _cleanup_free_ char *p = NULL;
240 Manager *m = userdata;
241 const char *name;
242 Seat *seat;
243 int r;
244
245 assert(bus);
98a28fef 246 assert(message);
cc377381 247 assert(m);
98a28fef 248
cc377381
LP
249 r = sd_bus_message_read(message, "s", &name);
250 if (r < 0)
251 return sd_bus_reply_method_errno(bus, message, r, NULL);
98a28fef 252
cc377381
LP
253 seat = hashmap_get(m->seats, name);
254 if (!seat)
255 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
98a28fef 256
cc377381
LP
257 p = seat_bus_path(seat);
258 if (!p)
259 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
98a28fef 260
cc377381
LP
261 return sd_bus_reply_method_return(bus, message, "o", p);
262}
98a28fef 263
cc377381
LP
264static int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata) {
265 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
266 Manager *m = userdata;
267 Session *session;
268 Iterator i;
269 int r;
270
271 assert(bus);
272 assert(message);
273 assert(m);
98a28fef 274
cc377381
LP
275 r = sd_bus_message_new_method_return(bus, message, &reply);
276 if (r < 0)
277 return sd_bus_reply_method_errno(bus, message, r, NULL);
98a28fef 278
cc377381
LP
279 r = sd_bus_message_open_container(reply, 'a', "(susso)");
280 if (r < 0)
281 return sd_bus_reply_method_errno(bus, message, r, NULL);
282
283 HASHMAP_FOREACH(session, m->sessions, i) {
284 _cleanup_free_ char *p = NULL;
285
286 p = session_bus_path(session);
287 if (!p)
288 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
289
290 r = sd_bus_message_append(reply, "(susso)",
291 session->id,
292 (uint32_t) session->user->uid,
293 session->user->name,
294 session->seat ? session->seat->id : "",
295 p);
296 if (r < 0)
297 return sd_bus_reply_method_errno(bus, message, r, NULL);
298 }
299
300 r = sd_bus_message_close_container(reply);
301 if (r < 0)
302 return sd_bus_reply_method_errno(bus, message, r, NULL);
303
304 return sd_bus_send(bus, reply, NULL);
305}
306
307static int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata) {
308 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
309 Manager *m = userdata;
310 User *user;
311 Iterator i;
312 int r;
313
314 assert(bus);
315 assert(message);
316 assert(m);
317
318 r = sd_bus_message_new_method_return(bus, message, &reply);
319 if (r < 0)
320 return sd_bus_reply_method_errno(bus, message, r, NULL);
321
322 r = sd_bus_message_open_container(reply, 'a', "(uso)");
323 if (r < 0)
324 return sd_bus_reply_method_errno(bus, message, r, NULL);
325
326 HASHMAP_FOREACH(user, m->users, i) {
327 _cleanup_free_ char *p = NULL;
328
329 p = user_bus_path(user);
330 if (!p)
331 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
332
333 r = sd_bus_message_append(reply, "(uso)",
334 (uint32_t) user->uid,
335 user->name,
336 p);
337 if (r < 0)
338 return sd_bus_reply_method_errno(bus, message, r, NULL);
339 }
340
341 r = sd_bus_message_close_container(reply);
342 if (r < 0)
343 return sd_bus_reply_method_errno(bus, message, r, NULL);
344
345 return sd_bus_send(bus, reply, NULL);
346}
347
348static int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata) {
349 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
350 Manager *m = userdata;
351 Seat *seat;
352 Iterator i;
353 int r;
354
355 assert(bus);
356 assert(message);
357 assert(m);
358
359 r = sd_bus_message_new_method_return(bus, message, &reply);
360 if (r < 0)
361 return sd_bus_reply_method_errno(bus, message, r, NULL);
362
363 r = sd_bus_message_open_container(reply, 'a', "(so)");
364 if (r < 0)
365 return sd_bus_reply_method_errno(bus, message, r, NULL);
366
367 HASHMAP_FOREACH(seat, m->seats, i) {
368 _cleanup_free_ char *p = NULL;
369
370 p = seat_bus_path(seat);
371 if (!p)
372 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
373
b8358bce 374 r = sd_bus_message_append(reply, "(so)", seat->id, p);
cc377381
LP
375 if (r < 0)
376 return sd_bus_reply_method_errno(bus, message, r, NULL);
377 }
378
379 r = sd_bus_message_close_container(reply);
380 if (r < 0)
381 return sd_bus_reply_method_errno(bus, message, r, NULL);
382
383 return sd_bus_send(bus, reply, NULL);
384}
385
386static int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata) {
387 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
388 Manager *m = userdata;
389 Inhibitor *inhibitor;
390 Iterator i;
391 int r;
392
393 r = sd_bus_message_new_method_return(bus, message, &reply);
394 if (r < 0)
395 return sd_bus_reply_method_errno(bus, message, r, NULL);
396
397 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
398 if (r < 0)
399 return sd_bus_reply_method_errno(bus, message, r, NULL);
400
401 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
402
403 r = sd_bus_message_append(reply, "ssssuu",
404 strempty(inhibit_what_to_string(inhibitor->what)),
405 strempty(inhibitor->who),
406 strempty(inhibitor->why),
407 strempty(inhibit_mode_to_string(inhibitor->mode)),
408 (uint32_t) inhibitor->uid,
409 (uint32_t) inhibitor->pid);
410 if (r < 0)
411 return sd_bus_reply_method_errno(bus, message, r, NULL);
412 }
413
414 r = sd_bus_message_close_container(reply);
415 if (r < 0)
416 return sd_bus_reply_method_errno(bus, message, r, NULL);
417
418 return sd_bus_send(bus, reply, NULL);
419}
420
421static int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
422 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host;
423 uint32_t uid, leader, audit_id = 0;
424 _cleanup_free_ char *id = NULL;
425 Session *session = NULL;
426 Manager *m = userdata;
427 User *user = NULL;
428 Seat *seat = NULL;
429 int remote;
430 uint32_t vtnr = 0;
431 SessionType t;
432 SessionClass c;
433 int r;
434
435 assert(bus);
436 assert(message);
437 assert(m);
438
439 r = sd_bus_message_read(message, "uussssussbss", &uid, &leader, &service, &type, &class, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
440 if (r < 0)
441 return sd_bus_reply_method_errno(bus, message, r, NULL);
442
443 if (leader == 1)
444 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
98a28fef 445
e2acb67b
LP
446 if (isempty(type))
447 t = _SESSION_TYPE_INVALID;
448 else {
449 t = session_type_from_string(type);
450 if (t < 0)
cc377381 451 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
e2acb67b 452 }
98a28fef 453
55efac6c 454 if (isempty(class))
e2acb67b
LP
455 c = _SESSION_CLASS_INVALID;
456 else {
55efac6c 457 c = session_class_from_string(class);
e2acb67b 458 if (c < 0)
cc377381 459 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
e2acb67b 460 }
55efac6c 461
954449b8
LP
462 if (isempty(cseat))
463 seat = NULL;
98a28fef 464 else {
954449b8
LP
465 seat = hashmap_get(m->seats, cseat);
466 if (!seat)
cc377381 467 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", seat);
98a28fef
LP
468 }
469
98a28fef 470 if (tty_is_vc(tty)) {
4d6d6518 471 int v;
98a28fef 472
954449b8 473 if (!seat)
92432fcc
DH
474 seat = m->seat0;
475 else if (seat != m->seat0)
cc377381 476 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat);
98a28fef 477
4d6d6518 478 v = vtnr_from_tty(tty);
4d6d6518 479 if (v <= 0)
cc377381 480 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
98a28fef
LP
481
482 if (vtnr <= 0)
4d6d6518
LP
483 vtnr = (uint32_t) v;
484 else if (vtnr != (uint32_t) v)
cc377381
LP
485 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
486
d1122ad5
LP
487 } else if (tty_is_console(tty)) {
488
954449b8 489 if (!seat)
92432fcc
DH
490 seat = m->seat0;
491 else if (seat != m->seat0)
cc377381 492 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
d1122ad5
LP
493
494 if (vtnr != 0)
cc377381 495 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
978cf3c7 496 }
98a28fef 497
954449b8 498 if (seat) {
bf7825ae 499 if (seat_has_vts(seat)) {
d1122ad5 500 if (vtnr > 63)
cc377381 501 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
4d6d6518 502 } else {
d1122ad5 503 if (vtnr != 0)
cc377381 504 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
4d6d6518
LP
505 }
506 }
507
cc377381
LP
508 r = sd_bus_message_enter_container(message, 'a', "(sv)");
509 if (r < 0)
510 return sd_bus_reply_method_errno(bus, message, r, NULL);
98a28fef 511
e2acb67b
LP
512 if (t == _SESSION_TYPE_INVALID) {
513 if (!isempty(display))
514 t = SESSION_X11;
515 else if (!isempty(tty))
516 t = SESSION_TTY;
517 else
518 t = SESSION_UNSPECIFIED;
519 }
520
521 if (c == _SESSION_CLASS_INVALID) {
522 if (!isempty(display) || !isempty(tty))
523 c = SESSION_USER;
524 else
525 c = SESSION_BACKGROUND;
526 }
527
9444b1f2 528 if (leader <= 0) {
cc377381
LP
529 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
530
531 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), (pid_t*) &leader);
532 if (r < 0)
533 return sd_bus_reply_method_errno(bus, message, r, NULL);
9444b1f2
LP
534 }
535
872c8faa 536 manager_get_session_by_pid(m, leader, &session);
fb6becb4 537 if (session) {
fb6becb4
LP
538 _cleanup_free_ char *path = NULL;
539 _cleanup_close_ int fifo_fd = -1;
98a28fef 540
fb6becb4
LP
541 /* Session already exists, client is probably
542 * something like "su" which changes uid but is still
543 * the same session */
98a28fef 544
954449b8 545 fifo_fd = session_create_fifo(session);
cc377381
LP
546 if (fifo_fd < 0)
547 return sd_bus_reply_method_errno(bus, message, fifo_fd, NULL);
98a28fef 548
fb6becb4 549 path = session_bus_path(session);
cc377381
LP
550 if (!path)
551 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
21c390cc 552
cc377381
LP
553 return sd_bus_reply_method_return(
554 bus, message, "soshsub",
555 session->id,
556 path,
557 session->user->runtime_path,
558 fifo_fd,
559 session->seat ? session->seat->id : "",
560 (uint32_t) session->vtnr,
561 true);
954449b8 562 }
21c390cc 563
954449b8
LP
564 audit_session_from_pid(leader, &audit_id);
565 if (audit_id > 0) {
566 /* Keep our session IDs and the audit session IDs in sync */
21c390cc 567
cc377381
LP
568 if (asprintf(&id, "%lu", (unsigned long) audit_id) < 0)
569 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
21c390cc 570
954449b8
LP
571 /* Wut? There's already a session by this name and we
572 * didn't find it above? Weird, then let's not trust
573 * the audit data and let's better register a new
574 * ID */
575 if (hashmap_get(m->sessions, id)) {
4b549144 576 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
954449b8 577 audit_id = 0;
8ea913b2 578
954449b8
LP
579 free(id);
580 id = NULL;
07714753 581 }
954449b8 582 }
07714753 583
954449b8 584 if (!id) {
07714753
LP
585 do {
586 free(id);
f8e2fb7b 587 id = NULL;
07714753 588
cc377381
LP
589 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
590 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
07714753
LP
591
592 } while (hashmap_get(m->sessions, id));
98a28fef
LP
593 }
594
954449b8 595 r = manager_add_user_by_uid(m, uid, &user);
cc377381
LP
596 if (r < 0) {
597 r = sd_bus_reply_method_errno(bus, message, r, NULL);
954449b8 598 goto fail;
cc377381 599 }
954449b8 600
9444b1f2 601 r = manager_add_session(m, id, &session);
cc377381
LP
602 if (r < 0) {
603 r = sd_bus_reply_method_errno(bus, message, r, NULL);
98a28fef 604 goto fail;
cc377381 605 }
98a28fef 606
9444b1f2
LP
607 session_set_user(session, user);
608
98a28fef
LP
609 session->leader = leader;
610 session->audit_id = audit_id;
611 session->type = t;
55efac6c 612 session->class = c;
98a28fef 613 session->remote = remote;
98a28fef
LP
614 session->vtnr = vtnr;
615
98a28fef
LP
616 if (!isempty(tty)) {
617 session->tty = strdup(tty);
618 if (!session->tty) {
cc377381 619 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
98a28fef
LP
620 goto fail;
621 }
622 }
623
624 if (!isempty(display)) {
625 session->display = strdup(display);
626 if (!session->display) {
cc377381 627 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
98a28fef
LP
628 goto fail;
629 }
630 }
631
632 if (!isempty(remote_user)) {
633 session->remote_user = strdup(remote_user);
634 if (!session->remote_user) {
cc377381 635 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
98a28fef
LP
636 goto fail;
637 }
638 }
639
640 if (!isempty(remote_host)) {
641 session->remote_host = strdup(remote_host);
642 if (!session->remote_host) {
cc377381 643 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
98a28fef
LP
644 goto fail;
645 }
646 }
647
648 if (!isempty(service)) {
649 session->service = strdup(service);
650 if (!session->service) {
cc377381 651 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
98a28fef
LP
652 goto fail;
653 }
654 }
655
954449b8
LP
656 if (seat) {
657 r = seat_attach_session(seat, session);
cc377381
LP
658 if (r < 0) {
659 r = sd_bus_reply_method_errno(bus, message, r, NULL);
98a28fef 660 goto fail;
cc377381 661 }
98a28fef
LP
662 }
663
664 r = session_start(session);
cc377381
LP
665 if (r < 0) {
666 r = sd_bus_reply_method_errno(bus, message, r, NULL);
98a28fef 667 goto fail;
cc377381 668 }
98a28fef 669
cc377381 670 session->create_message = sd_bus_message_ref(message);
98a28fef 671
cba38758
LP
672 /* Now, let's wait until the slice unit and stuff got
673 * created. We send the reply back from
674 * session_send_create_reply().*/
675
cc377381 676 return 1;
98a28fef
LP
677
678fail:
98a28fef
LP
679 if (session)
680 session_add_to_gc_queue(session);
681
682 if (user)
683 user_add_to_gc_queue(user);
684
98a28fef
LP
685 return r;
686}
687
cc377381
LP
688static int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
689 Manager *m = userdata;
690 Session *session;
691 const char *name;
692 int r;
314b4b0a 693
cc377381
LP
694 assert(bus);
695 assert(message);
696 assert(m);
697
698 r = sd_bus_message_read(message, "s", &name);
699 if (r < 0)
700 return sd_bus_reply_method_errno(bus, message, r, NULL);
701
702 session = hashmap_get(m->sessions, name);
703 if (!session)
704 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
705
706 /* We use the FIFO to detect stray sessions where the process
707 invoking PAM dies abnormally. We need to make sure that
708 that process is not killed if at the clean end of the
709 session it closes the FIFO. Hence, with this call
710 explicitly turn off the FIFO logic, so that the PAM code
711 can finish clean up on its own */
712 session_remove_fifo(session);
713 session_save(session);
714 user_save(session->user);
715
716 return sd_bus_reply_method_return(bus, message, NULL);
717}
718
719static int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
720 Manager *m = userdata;
721 Session *session;
722 const char *name;
723 int r;
f8e2fb7b 724
cc377381
LP
725 assert(bus);
726 assert(message);
f8e2fb7b 727 assert(m);
cc377381
LP
728
729 r = sd_bus_message_read(message, "s", &name);
730 if (r < 0)
731 return sd_bus_reply_method_errno(bus, message, r, NULL);
732
733 session = hashmap_get(m->sessions, name);
734 if (!session)
735 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
736
737 r = session_activate(session);
738 if (r < 0)
739 return sd_bus_reply_method_errno(bus, message, r, NULL);
740
741 return sd_bus_reply_method_return(bus, message, NULL);
742}
743
744static int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata) {
745 const char *session_name, *seat_name;
746 Manager *m = userdata;
747 Session *session;
748 Seat *seat;
749 int r;
750
751 assert(bus);
f8e2fb7b 752 assert(message);
cc377381 753 assert(m);
f8e2fb7b 754
cc377381
LP
755 /* Same as ActivateSession() but refuses to work if
756 * the seat doesn't match */
f8e2fb7b 757
cc377381
LP
758 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
759 if (r < 0)
760 return sd_bus_reply_method_errno(bus, message, r, NULL);
eecd1362 761
cc377381
LP
762 session = hashmap_get(m->sessions, session_name);
763 if (!session)
764 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", session_name);
beaafb2e 765
cc377381
LP
766 seat = hashmap_get(m->seats, seat_name);
767 if (!seat)
768 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", seat_name);
314b4b0a 769
cc377381
LP
770 if (session->seat != seat)
771 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
772
773 r = session_activate(session);
f8e2fb7b 774 if (r < 0)
cc377381 775 return sd_bus_reply_method_errno(bus, message, r, NULL);
f8e2fb7b 776
cc377381
LP
777 return sd_bus_reply_method_return(bus, message, NULL);
778}
f8e2fb7b 779
cc377381
LP
780static int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
781 Manager *m = userdata;
782 Session *session;
783 const char *name;
784 int r;
f8e2fb7b 785
cc377381
LP
786 assert(bus);
787 assert(message);
788 assert(m);
f8e2fb7b 789
cc377381
LP
790 r = sd_bus_message_read(message, "s", &name);
791 if (r < 0)
792 return sd_bus_reply_method_errno(bus, message, r, NULL);
f8e2fb7b 793
cc377381
LP
794 session = hashmap_get(m->sessions, name);
795 if (!session)
796 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
f8e2fb7b 797
cc377381 798 r = session_send_lock(session, streq(sd_bus_message_get_member(message), "LockSession"));
f8e2fb7b 799 if (r < 0)
cc377381 800 return sd_bus_reply_method_errno(bus, message, r, NULL);
f8e2fb7b 801
cc377381
LP
802 return sd_bus_reply_method_return(bus, message, NULL);
803}
f8e2fb7b 804
cc377381
LP
805static int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata) {
806 Manager *m = userdata;
807 int r;
f8e2fb7b 808
cc377381
LP
809 assert(bus);
810 assert(message);
811 assert(m);
f8e2fb7b 812
cc377381
LP
813 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
814 if (r < 0)
815 return sd_bus_reply_method_errno(bus, message, r, NULL);
f8e2fb7b 816
cc377381
LP
817 return sd_bus_reply_method_return(bus, message, NULL);
818}
819
820static int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
821 const char *name, *swho;
822 Manager *m = userdata;
823 Session *session;
824 int32_t signo;
825 KillWho who;
826 int r;
827
828 assert(bus);
829 assert(message);
830 assert(m);
831
832 r = sd_bus_message_read(message, "ssi", &name, &swho, &signo);
833 if (r < 0)
834 return sd_bus_reply_method_errno(bus, message, r, NULL);
835
836 if (isempty(swho))
837 who = KILL_ALL;
838 else {
839 who = kill_who_from_string(swho);
840 if (who < 0)
841 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
f8e2fb7b
LP
842 }
843
cc377381
LP
844 if (signo <= 0 || signo >= _NSIG)
845 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
f8e2fb7b 846
cc377381
LP
847 session = hashmap_get(m->sessions, name);
848 if (!session)
849 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
f8e2fb7b 850
cc377381
LP
851 r = session_kill(session, who, signo);
852 if (r < 0)
853 return sd_bus_reply_method_errno(bus, message, r, NULL);
f8e2fb7b 854
cc377381
LP
855 return sd_bus_reply_method_return(bus, message, NULL);
856}
f8e2fb7b 857
cc377381
LP
858static int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata) {
859 Manager *m = userdata;
860 uint32_t uid;
861 int32_t signo;
862 User *user;
863 int r;
f8e2fb7b 864
cc377381
LP
865 assert(bus);
866 assert(message);
867 assert(m);
868
869 r = sd_bus_message_read(message, "ui", &uid, &signo);
870 if (r < 0)
871 return sd_bus_reply_method_errno(bus, message, r, NULL);
872
873 if (signo <= 0 || signo >= _NSIG)
874 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
875
876 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
877 if (!user)
878 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_USER, "No user '%lu' known or logged in", (unsigned long) uid);
879
880 r = user_kill(user, signo);
881 if (r < 0)
882 return sd_bus_reply_method_errno(bus, message, r, NULL);
883
884 return sd_bus_reply_method_return(bus, message, NULL);
885}
886
887static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata) {
888 Manager *m = userdata;
889 const char *name;
890 Session *session;
891 int r;
892
893 assert(bus);
894 assert(message);
895 assert(m);
896
897 r = sd_bus_message_read(message, "s", &name);
898 if (r < 0)
899 return sd_bus_reply_method_errno(bus, message, r, NULL);
900
901 session = hashmap_get(m->sessions, name);
902 if (!session)
903 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
904
905 r = session_stop(session);
906 if (r < 0)
907 return sd_bus_reply_method_errno(bus, message, r, NULL);
908
909 return sd_bus_reply_method_return(bus, message, NULL);
910}
911
912static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata) {
913 Manager *m = userdata;
914 uint32_t uid;
915 User *user;
916 int r;
917
918 assert(bus);
919 assert(message);
920 assert(m);
921
922 r = sd_bus_message_read(message, "u", &uid);
923 if (r < 0)
924 return sd_bus_reply_method_errno(bus, message, r, NULL);
925
926 user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
927 if (!user)
928 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_USER, "No user '%lu' known or logged in", (unsigned long) uid);
929
930 r = user_stop(user);
931 if (r < 0)
932 return sd_bus_reply_method_errno(bus, message, r, NULL);
933
934 return sd_bus_reply_method_return(bus, message, NULL);
935}
936
937static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata) {
938 Manager *m = userdata;
939 const char *name;
940 Seat *seat;
941 int r;
942
943 assert(bus);
944 assert(message);
945 assert(m);
946
947 r = sd_bus_message_read(message, "s", &name);
948 if (r < 0)
949 return sd_bus_reply_method_errno(bus, message, r, NULL);
950
951 seat = hashmap_get(m->seats, name);
952 if (!seat)
953 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
954
955 r = seat_stop_sessions(seat);
956 if (r < 0)
957 return sd_bus_reply_method_errno(bus, message, r, NULL);
958
959 return sd_bus_reply_method_return(bus, message, NULL);
960}
961
962static int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata) {
963 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
964 _cleanup_free_ char *cc = NULL;
965 Manager *m = userdata;
966 int b, r;
967 struct passwd *pw;
968 const char *path;
969 uint32_t uid;
970 int interactive;
971
972 assert(bus);
973 assert(message);
974 assert(m);
975
976 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
977 if (r < 0)
978 return sd_bus_reply_method_errno(bus, message, r, NULL);
979
980 errno = 0;
981 pw = getpwuid(uid);
982 if (!pw)
983 return sd_bus_reply_method_errno(bus, message, errno ? errno : ENOENT, NULL);
984
985 r = bus_verify_polkit_async(bus,
986 &m->polkit_registry,
987 message,
988 "org.freedesktop.login1.set-user-linger",
989 interactive,
990 &error,
991 method_set_user_linger, m);
992 if (r < 0)
993 return sd_bus_reply_method_errno(bus, message, r, &error);
994 if (r == 0)
995 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
996
997 mkdir_p_label("/var/lib/systemd", 0755);
998
999 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1000 if (r < 0)
1001 return sd_bus_reply_method_errno(bus, message, r, NULL);
1002
1003 cc = cescape(pw->pw_name);
1004 if (!cc)
1005 return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
1006
1007 path = strappenda("/var/lib/systemd/linger/", cc);
1008 if (b) {
1009 User *u;
1010
1011 r = touch(path);
1012 if (r < 0)
1013 return sd_bus_reply_method_errno(bus, message, r, NULL);
1014
1015 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1016 user_start(u);
1017
1018 } else {
1019 User *u;
1020
1021 r = unlink(path);
1022 if (r < 0 && errno != ENOENT)
1023 return sd_bus_reply_method_errno(bus, message, errno, NULL);
1024
1025 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
1026 if (u)
1027 user_add_to_gc_queue(u);
1028 }
1029
1030 return sd_bus_reply_method_return(bus, message, NULL);
f8e2fb7b
LP
1031}
1032
2eb916cd 1033static int trigger_device(Manager *m, struct udev_device *d) {
b668e064
LP
1034 struct udev_enumerate *e;
1035 struct udev_list_entry *first, *item;
1036 int r;
1037
1038 assert(m);
1039
1040 e = udev_enumerate_new(m->udev);
1041 if (!e) {
1042 r = -ENOMEM;
1043 goto finish;
1044 }
1045
2eb916cd
LP
1046 if (d) {
1047 if (udev_enumerate_add_match_parent(e, d) < 0) {
1048 r = -EIO;
1049 goto finish;
1050 }
1051 }
1052
b668e064
LP
1053 if (udev_enumerate_scan_devices(e) < 0) {
1054 r = -EIO;
1055 goto finish;
1056 }
1057
1058 first = udev_enumerate_get_list_entry(e);
1059 udev_list_entry_foreach(item, first) {
cc377381 1060 _cleanup_free_ char *t = NULL;
b668e064
LP
1061 const char *p;
1062
1063 p = udev_list_entry_get_name(item);
1064
b668e064
LP
1065 t = strappend(p, "/uevent");
1066 if (!t) {
1067 r = -ENOMEM;
1068 goto finish;
1069 }
1070
574d5f2d 1071 write_string_file(t, "change");
b668e064
LP
1072 }
1073
1074 r = 0;
1075
1076finish:
1077 if (e)
1078 udev_enumerate_unref(e);
1079
1080 return r;
1081}
1082
47a26690 1083static int attach_device(Manager *m, const char *seat, const char *sysfs) {
7fd1b19b 1084 _cleanup_free_ char *rule = NULL, *file = NULL;
c28fa3d3 1085 const char *id_for_seat;
cc377381 1086 struct udev_device *d;
47a26690
LP
1087 int r;
1088
1089 assert(m);
1090 assert(seat);
1091 assert(sysfs);
1092
1093 d = udev_device_new_from_syspath(m->udev, sysfs);
1094 if (!d)
1095 return -ENODEV;
1096
309c2a2c 1097 if (!udev_device_has_tag(d, "seat")) {
47a26690
LP
1098 r = -ENODEV;
1099 goto finish;
1100 }
1101
c28fa3d3
LP
1102 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1103 if (!id_for_seat) {
47a26690
LP
1104 r = -ENODEV;
1105 goto finish;
1106 }
1107
c28fa3d3 1108 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0) {
47a26690
LP
1109 r = -ENOMEM;
1110 goto finish;
1111 }
1112
c28fa3d3 1113 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) {
47a26690
LP
1114 r = -ENOMEM;
1115 goto finish;
1116 }
1117
d2e54fae 1118 mkdir_p_label("/etc/udev/rules.d", 0755);
a5c32cff 1119 label_init("/etc");
574d5f2d 1120 r = write_string_file_atomic_label(file, rule);
a0a0c7f1
LP
1121 if (r < 0)
1122 goto finish;
1123
2eb916cd 1124 r = trigger_device(m, d);
47a26690
LP
1125
1126finish:
47a26690
LP
1127 if (d)
1128 udev_device_unref(d);
1129
1130 return r;
1131}
1132
b668e064 1133static int flush_devices(Manager *m) {
7fd1b19b 1134 _cleanup_closedir_ DIR *d;
b668e064
LP
1135
1136 assert(m);
1137
1138 d = opendir("/etc/udev/rules.d");
1139 if (!d) {
1140 if (errno != ENOENT)
1141 log_warning("Failed to open /etc/udev/rules.d: %m");
1142 } else {
1143 struct dirent *de;
1144
1145 while ((de = readdir(d))) {
1146
1147 if (!dirent_is_file(de))
1148 continue;
1149
1150 if (!startswith(de->d_name, "72-seat-"))
1151 continue;
1152
1153 if (!endswith(de->d_name, ".rules"))
1154 continue;
1155
1156 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1157 log_warning("Failed to unlink %s: %m", de->d_name);
1158 }
b668e064
LP
1159 }
1160
1161 return trigger_device(m, NULL);
1162}
1163
cc377381
LP
1164static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata) {
1165 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1166 const char *sysfs, *seat;
1167 Manager *m = userdata;
1168 int interactive, r;
1169
1170 assert(bus);
1171 assert(message);
1172 assert(m);
1173
1174 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1175 if (r < 0)
1176 return sd_bus_reply_method_errno(bus, message, r, NULL);
1177
1178 if (!path_startswith(sysfs, "/sys"))
1179 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1180
1181 if (!seat_name_is_valid(seat))
1182 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1183
1184 r = bus_verify_polkit_async(bus,
1185 &m->polkit_registry,
1186 message,
1187 "org.freedesktop.login1.attach-device",
1188 interactive,
1189 &error,
1190 method_attach_device, m);
1191 if (r < 0)
1192 return sd_bus_reply_method_errno(bus, message, r, &error);
1193 if (r == 0)
1194 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1195
1196 r = attach_device(m, seat, sysfs);
1197 if (r < 0)
1198 return sd_bus_reply_method_errno(bus, message, r, NULL);
1199
1200 return sd_bus_reply_method_return(bus, message, NULL);
1201}
1202
1203static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata) {
1204 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1205 Manager *m = userdata;
1206 int interactive, r;
1207
1208 assert(bus);
1209 assert(message);
1210 assert(m);
1211
1212 r = sd_bus_message_read(message, "b", &interactive);
1213 if (r < 0)
1214 return sd_bus_reply_method_errno(bus, message, r, NULL);
1215
1216 r = bus_verify_polkit_async(bus,
1217 &m->polkit_registry,
1218 message,
1219 "org.freedesktop.login1.flush-devices",
1220 interactive,
1221 &error,
1222 method_flush_devices, m);
1223 if (r < 0)
1224 return sd_bus_reply_method_errno(bus, message, r, &error);
1225 if (r == 0)
1226 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1227
1228 r = flush_devices(m);
1229 if (r < 0)
1230 return sd_bus_reply_method_errno(bus, message, r, &error);
1231
1232 return sd_bus_reply_method_return(bus, message, NULL);
1233}
1234
89f13440 1235static int have_multiple_sessions(
89f13440 1236 Manager *m,
409133be 1237 uid_t uid) {
89f13440 1238
2154761f
MS
1239 Session *session;
1240 Iterator i;
89f13440
LP
1241
1242 assert(m);
1243
1ca04b87
LP
1244 /* Check for other users' sessions. Greeter sessions do not
1245 * count, and non-login sessions do not count either. */
2154761f 1246 HASHMAP_FOREACH(session, m->sessions, i)
1ca04b87 1247 if (session->class == SESSION_USER &&
c68ba912 1248 !session->closing &&
1ca04b87 1249 session->user->uid != uid)
2154761f 1250 return true;
89f13440
LP
1251
1252 return false;
1253}
1254
314b4b0a
LP
1255static int bus_manager_log_shutdown(
1256 Manager *m,
1257 InhibitWhat w,
1258 const char *unit_name) {
1259
1260 const char *p, *q;
1261
1262 assert(m);
1263 assert(unit_name);
1264
1265 if (w != INHIBIT_SHUTDOWN)
1266 return 0;
1267
1268 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1269 p = "MESSAGE=System is powering down.";
1270 q = "SHUTDOWN=power-off";
1271 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1272 p = "MESSAGE=System is halting.";
1273 q = "SHUTDOWN=halt";
1274 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1275 p = "MESSAGE=System is rebooting.";
1276 q = "SHUTDOWN=reboot";
1277 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1278 p = "MESSAGE=System is rebooting with kexec.";
1279 q = "SHUTDOWN=kexec";
1280 } else {
1281 p = "MESSAGE=System is shutting down.";
1282 q = NULL;
1283 }
1284
1285 return log_struct(LOG_NOTICE, MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1286 p,
1287 q, NULL);
1288}
1289
1290static int execute_shutdown_or_sleep(
1291 Manager *m,
1292 InhibitWhat w,
1293 const char *unit_name,
cc377381 1294 sd_bus_error *error) {
314b4b0a 1295
cc377381
LP
1296 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1297 const char *p;
af9792ac 1298 char *c;
cc377381 1299 int r;
eecd1362 1300
af9792ac 1301 assert(m);
314b4b0a
LP
1302 assert(w >= 0);
1303 assert(w < _INHIBIT_WHAT_MAX);
d889a206 1304 assert(unit_name);
eecd1362 1305
314b4b0a
LP
1306 bus_manager_log_shutdown(m, w, unit_name);
1307
cc377381 1308 r = sd_bus_call_method(
af9792ac 1309 m->bus,
eecd1362
LP
1310 "org.freedesktop.systemd1",
1311 "/org/freedesktop/systemd1",
1312 "org.freedesktop.systemd1.Manager",
b9c26b41 1313 "StartUnit",
af9792ac 1314 error,
cc377381
LP
1315 &reply,
1316 "ss", unit_name, "replace-irreversibly");
af9792ac
LP
1317 if (r < 0)
1318 return r;
1319
cc377381
LP
1320 r = sd_bus_message_read(reply, "o", &p);
1321 if (r < 0)
1322 return r;
af9792ac
LP
1323
1324 c = strdup(p);
1325 if (!c)
1326 return -ENOMEM;
1327
314b4b0a 1328 m->action_unit = unit_name;
af9792ac
LP
1329 free(m->action_job);
1330 m->action_job = c;
314b4b0a 1331 m->action_what = w;
af9792ac
LP
1332
1333 return 0;
eecd1362
LP
1334}
1335
314b4b0a
LP
1336static int delay_shutdown_or_sleep(
1337 Manager *m,
1338 InhibitWhat w,
1339 const char *unit_name) {
eecd1362 1340
eecd1362 1341 assert(m);
d889a206
LP
1342 assert(w >= 0);
1343 assert(w < _INHIBIT_WHAT_MAX);
314b4b0a 1344 assert(unit_name);
eecd1362 1345
314b4b0a
LP
1346 m->action_timestamp = now(CLOCK_MONOTONIC);
1347 m->action_unit = unit_name;
1348 m->action_what = w;
d889a206
LP
1349
1350 return 0;
1351}
1352
cc377381 1353static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
d889a206 1354
cc377381
LP
1355 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1356 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1357 [INHIBIT_SLEEP] = "PrepareForSleep"
1358 };
1359
1360 int active = _active;
877d54e9
LP
1361
1362 assert(m);
314b4b0a
LP
1363 assert(w >= 0);
1364 assert(w < _INHIBIT_WHAT_MAX);
1365 assert(signal_name[w]);
877d54e9 1366
cc377381
LP
1367 return sd_bus_emit_signal(m->bus,
1368 "/org/freedesktop/login1",
1369 "org.freedesktop.login1.Manager",
1370 signal_name[w],
1371 "b",
1372 &active);
877d54e9
LP
1373}
1374
069cfc85
LP
1375int bus_manager_shutdown_or_sleep_now_or_later(
1376 Manager *m,
1377 const char *unit_name,
1378 InhibitWhat w,
cc377381 1379 sd_bus_error *error) {
069cfc85
LP
1380
1381 bool delayed;
1382 int r;
1383
1384 assert(m);
1385 assert(unit_name);
1386 assert(w >= 0);
1387 assert(w <= _INHIBIT_WHAT_MAX);
af9792ac 1388 assert(!m->action_job);
069cfc85 1389
314b4b0a
LP
1390 /* Tell everybody to prepare for shutdown/sleep */
1391 send_prepare_for(m, w, true);
1392
069cfc85
LP
1393 delayed =
1394 m->inhibit_delay_max > 0 &&
409133be 1395 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0);
069cfc85
LP
1396
1397 if (delayed)
1398 /* Shutdown is delayed, keep in mind what we
1399 * want to do, and start a timeout */
1400 r = delay_shutdown_or_sleep(m, w, unit_name);
314b4b0a 1401 else
069cfc85
LP
1402 /* Shutdown is not delayed, execute it
1403 * immediately */
314b4b0a 1404 r = execute_shutdown_or_sleep(m, w, unit_name, error);
069cfc85
LP
1405
1406 return r;
1407}
1408
cc377381 1409static int method_do_shutdown_or_sleep(
d889a206 1410 Manager *m,
cc377381 1411 sd_bus_message *message,
d889a206
LP
1412 const char *unit_name,
1413 InhibitWhat w,
1414 const char *action,
1415 const char *action_multiple_sessions,
1416 const char *action_ignore_inhibit,
19adb8a3 1417 const char *sleep_verb,
cc377381 1418 sd_bus_message_handler_t method) {
d889a206 1419
cc377381 1420 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
069cfc85 1421 bool multiple_sessions, blocked;
cc377381
LP
1422 int interactive, r;
1423 uid_t uid;
d889a206
LP
1424
1425 assert(m);
d889a206
LP
1426 assert(message);
1427 assert(unit_name);
1428 assert(w >= 0);
1429 assert(w <= _INHIBIT_WHAT_MAX);
1430 assert(action);
1431 assert(action_multiple_sessions);
1432 assert(action_ignore_inhibit);
cc377381
LP
1433 assert(method);
1434
1435 r = sd_bus_message_read(message, "b", &interactive);
1436 if (r < 0)
1437 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
d889a206 1438
314b4b0a
LP
1439 /* Don't allow multiple jobs being executed at the same time */
1440 if (m->action_what)
cc377381 1441 return sd_bus_reply_method_errorf(m->bus, message, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
d889a206 1442
19adb8a3
ZJS
1443 if (sleep_verb) {
1444 r = can_sleep(sleep_verb);
6524990f 1445 if (r < 0)
cc377381 1446 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
6524990f
LP
1447
1448 if (r == 0)
cc377381 1449 return sd_bus_reply_method_errorf(m->bus, message, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
6524990f
LP
1450 }
1451
cc377381
LP
1452 r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
1453 if (r < 0)
1454 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
409133be 1455
cc377381 1456 r = have_multiple_sessions(m, uid);
d889a206 1457 if (r < 0)
cc377381 1458 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
d889a206
LP
1459
1460 multiple_sessions = r > 0;
cc377381 1461 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid);
d889a206
LP
1462
1463 if (multiple_sessions) {
cc377381
LP
1464 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
1465 action_multiple_sessions, interactive, &error, method, m);
d889a206 1466 if (r < 0)
cc377381 1467 return sd_bus_reply_method_errno(m->bus, message, r, &error);
d889a206
LP
1468 }
1469
1470 if (blocked) {
cc377381
LP
1471 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
1472 action_ignore_inhibit, interactive, &error, method, m);
d889a206 1473 if (r < 0)
cc377381 1474 return sd_bus_reply_method_errno(m->bus, message, r, &error);
d889a206
LP
1475 }
1476
1477 if (!multiple_sessions && !blocked) {
cc377381
LP
1478 r = bus_verify_polkit_async(m->bus, &m->polkit_registry, message,
1479 action, interactive, &error, method, m);
d889a206 1480 if (r < 0)
cc377381 1481 return sd_bus_reply_method_errno(m->bus, message, r, &error);
d889a206
LP
1482 }
1483
cc377381 1484 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, &error);
d889a206 1485 if (r < 0)
cc377381 1486 return sd_bus_reply_method_errno(m->bus, message, r, &error);
d889a206 1487
cc377381 1488 return sd_bus_reply_method_return(m->bus, message, NULL);
eecd1362
LP
1489}
1490
cc377381 1491static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata) {
3f49d45a
LP
1492 Manager *m = userdata;
1493
cc377381
LP
1494 return method_do_shutdown_or_sleep(
1495 m, message,
1496 SPECIAL_POWEROFF_TARGET,
1497 INHIBIT_SHUTDOWN,
1498 "org.freedesktop.login1.power-off",
1499 "org.freedesktop.login1.power-off-multiple-sessions",
1500 "org.freedesktop.login1.power-off-ignore-inhibit",
1501 NULL,
1502 method_poweroff);
1503}
88e3dc90 1504
cc377381
LP
1505static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata) {
1506 Manager *m = userdata;
88e3dc90 1507
cc377381
LP
1508 return method_do_shutdown_or_sleep(
1509 m, message,
1510 SPECIAL_REBOOT_TARGET,
1511 INHIBIT_SHUTDOWN,
1512 "org.freedesktop.login1.reboot",
1513 "org.freedesktop.login1.reboot-multiple-sessions",
1514 "org.freedesktop.login1.reboot-ignore-inhibit",
1515 NULL,
1516 method_reboot);
1517}
88e3dc90 1518
cc377381
LP
1519static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata) {
1520 Manager *m = userdata;
88e3dc90 1521
cc377381
LP
1522 return method_do_shutdown_or_sleep(
1523 m, message,
1524 SPECIAL_SUSPEND_TARGET,
1525 INHIBIT_SLEEP,
1526 "org.freedesktop.login1.suspend",
1527 "org.freedesktop.login1.suspend-multiple-sessions",
1528 "org.freedesktop.login1.suspend-ignore-inhibit",
1529 "suspend",
1530 method_suspend);
1531}
88e3dc90 1532
cc377381
LP
1533static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata) {
1534 Manager *m = userdata;
b6160029 1535
cc377381
LP
1536 return method_do_shutdown_or_sleep(
1537 m, message,
1538 SPECIAL_HIBERNATE_TARGET,
1539 INHIBIT_SLEEP,
1540 "org.freedesktop.login1.hibernate",
1541 "org.freedesktop.login1.hibernate-multiple-sessions",
1542 "org.freedesktop.login1.hibernate-ignore-inhibit",
1543 "hibernate",
1544 method_hibernate);
1545}
fa2b196d 1546
cc377381
LP
1547static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata) {
1548 Manager *m = userdata;
fa2b196d 1549
cc377381
LP
1550 return method_do_shutdown_or_sleep(
1551 m, message,
1552 SPECIAL_HYBRID_SLEEP_TARGET,
1553 INHIBIT_SLEEP,
1554 "org.freedesktop.login1.hibernate",
1555 "org.freedesktop.login1.hibernate-multiple-sessions",
1556 "org.freedesktop.login1.hibernate-ignore-inhibit",
1557 "hybrid-sleep",
1558 method_hybrid_sleep);
1559}
de07ab16 1560
cc377381
LP
1561static int method_can_shutdown_or_sleep(
1562 Manager *m,
1563 sd_bus_message *message,
1564 InhibitWhat w,
1565 const char *action,
1566 const char *action_multiple_sessions,
1567 const char *action_ignore_inhibit,
1568 const char *sleep_verb) {
de07ab16 1569
cc377381
LP
1570 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1571 bool multiple_sessions, challenge, blocked;
1572 const char *result = NULL;
1573 uid_t uid;
1574 int r;
de07ab16 1575
cc377381
LP
1576 assert(m);
1577 assert(message);
1578 assert(w >= 0);
1579 assert(w <= _INHIBIT_WHAT_MAX);
1580 assert(action);
1581 assert(action_multiple_sessions);
1582 assert(action_ignore_inhibit);
de07ab16 1583
cc377381
LP
1584 if (sleep_verb) {
1585 r = can_sleep(sleep_verb);
de07ab16 1586 if (r < 0)
cc377381
LP
1587 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
1588 if (r == 0)
1589 return sd_bus_reply_method_return(m->bus, message, "s", "na");
1590 }
de07ab16 1591
cc377381
LP
1592 r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
1593 if (r < 0)
1594 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
de07ab16 1595
cc377381
LP
1596 r = have_multiple_sessions(m, uid);
1597 if (r < 0)
1598 return sd_bus_reply_method_errno(m->bus, message, r, NULL);
de07ab16 1599
cc377381
LP
1600 multiple_sessions = r > 0;
1601 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid);
de07ab16 1602
cc377381
LP
1603 if (multiple_sessions) {
1604 r = bus_verify_polkit(m->bus, message, action_multiple_sessions, false, &challenge, &error);
de07ab16 1605 if (r < 0)
cc377381 1606 return sd_bus_reply_method_errno(m->bus, message, r, &error);
bef422ae 1607
cc377381
LP
1608 if (r > 0)
1609 result = "yes";
1610 else if (challenge)
1611 result = "challenge";
1612 else
1613 result = "no";
1614 }
bef422ae 1615
cc377381
LP
1616 if (blocked) {
1617 r = bus_verify_polkit(m->bus, message, action_ignore_inhibit, false, &challenge, &error);
bef422ae 1618 if (r < 0)
cc377381 1619 return sd_bus_reply_method_errno(m->bus, message, r, &error);
bef422ae 1620
cc377381
LP
1621 if (r > 0 && !result)
1622 result = "yes";
1623 else if (challenge && (!result || streq(result, "yes")))
1624 result = "challenge";
1625 else
1626 result = "no";
1627 }
bef422ae 1628
cc377381
LP
1629 if (!multiple_sessions && !blocked) {
1630 /* If neither inhibit nor multiple sessions
1631 * apply then just check the normal policy */
bef422ae 1632
cc377381 1633 r = bus_verify_polkit(m->bus, message, action, false, &challenge, &error);
bef422ae 1634 if (r < 0)
cc377381 1635 return sd_bus_reply_method_errno(m->bus, message, r, &error);
bef422ae 1636
cc377381
LP
1637 if (r > 0)
1638 result = "yes";
1639 else if (challenge)
1640 result = "challenge";
1641 else
1642 result = "no";
1643 }
bef422ae 1644
cc377381
LP
1645 return sd_bus_reply_method_return(m->bus, message, "s", result);
1646}
bef422ae 1647
cc377381
LP
1648static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata) {
1649 Manager *m = userdata;
bef422ae 1650
cc377381
LP
1651 return method_can_shutdown_or_sleep(
1652 m, message,
1653 INHIBIT_SHUTDOWN,
1654 "org.freedesktop.login1.power-off",
1655 "org.freedesktop.login1.power-off-multiple-sessions",
1656 "org.freedesktop.login1.power-off-ignore-inhibit",
1657 NULL);
1658}
bef422ae 1659
cc377381
LP
1660static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata) {
1661 Manager *m = userdata;
bef422ae 1662
cc377381
LP
1663 return method_can_shutdown_or_sleep(
1664 m, message,
1665 INHIBIT_SHUTDOWN,
1666 "org.freedesktop.login1.reboot",
1667 "org.freedesktop.login1.reboot-multiple-sessions",
1668 "org.freedesktop.login1.reboot-ignore-inhibit",
1669 NULL);
1670}
bef422ae 1671
cc377381
LP
1672static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata) {
1673 Manager *m = userdata;
7f7bb946 1674
cc377381
LP
1675 return method_can_shutdown_or_sleep(
1676 m, message,
1677 INHIBIT_SLEEP,
1678 "org.freedesktop.login1.suspend",
1679 "org.freedesktop.login1.suspend-multiple-sessions",
1680 "org.freedesktop.login1.suspend-ignore-inhibit",
1681 "suspend");
1682}
7f7bb946 1683
cc377381
LP
1684static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata) {
1685 Manager *m = userdata;
02b16a19 1686
cc377381
LP
1687 return method_can_shutdown_or_sleep(
1688 m, message,
1689 INHIBIT_SLEEP,
1690 "org.freedesktop.login1.hibernate",
1691 "org.freedesktop.login1.hibernate-multiple-sessions",
1692 "org.freedesktop.login1.hibernate-ignore-inhibit",
1693 "hibernate");
1694}
7f7bb946 1695
cc377381
LP
1696static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata) {
1697 Manager *m = userdata;
7f7bb946 1698
cc377381
LP
1699 return method_can_shutdown_or_sleep(
1700 m, message,
1701 INHIBIT_SLEEP,
1702 "org.freedesktop.login1.hibernate",
1703 "org.freedesktop.login1.hibernate-multiple-sessions",
1704 "org.freedesktop.login1.hibernate-ignore-inhibit",
1705 "hybrid-sleep");
1706}
38f3fc7d 1707
cc377381
LP
1708static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata) {
1709 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1710 const char *who, *why, *what, *mode;
1711 _cleanup_free_ char *id = NULL;
1712 _cleanup_close_ int fifo_fd = -1;
1713 Manager *m = userdata;
1714 Inhibitor *i = NULL;
1715 InhibitMode mm;
1716 InhibitWhat w;
1717 pid_t pid;
1718 uid_t uid;
1719 int r;
7f7bb946 1720
cc377381
LP
1721 assert(bus);
1722 assert(message);
1723 assert(m);
38f3fc7d 1724
cc377381
LP
1725 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
1726 if (r < 0)
1727 return sd_bus_reply_method_errno(bus, message, r, NULL);
38f3fc7d 1728
cc377381
LP
1729 w = inhibit_what_from_string(what);
1730 if (w <= 0)
1731 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
38f3fc7d 1732
cc377381
LP
1733 mm = inhibit_mode_from_string(mode);
1734 if (mm < 0)
1735 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
7f7bb946 1736
cc377381
LP
1737 /* Delay is only supported for shutdown/sleep */
1738 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
1739 return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
38f3fc7d 1740
cc377381
LP
1741 /* Don't allow taking delay locks while we are already
1742 * executing the operation. We shouldn't create the impression
1743 * that the lock was successful if the machine is about to go
1744 * down/suspend any moment. */
1745 if (m->action_what & w)
1746 return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
1747
1748 r = bus_verify_polkit_async(bus, &m->polkit_registry, message,
1749 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
1750 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
1751 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
1752 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
1753 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
1754 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
1755 "org.freedesktop.login1.inhibit-handle-lid-switch",
1756 false, &error, method_inhibit, m);
1757 if (r < 0)
1758 return sd_bus_reply_method_errno(bus, message, r, &error);
1759 if (r == 0)
1760 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
7f7bb946 1761
cc377381
LP
1762 r = sd_bus_get_owner_uid(m->bus, sd_bus_message_get_sender(message), &uid);
1763 if (r < 0)
1764 return sd_bus_reply_method_errno(bus, message, r, NULL);
7f7bb946 1765
cc377381
LP
1766 r = sd_bus_get_owner_pid(m->bus, sd_bus_message_get_sender(message), &pid);
1767 if (r < 0)
1768 return sd_bus_reply_method_errno(bus, message, r, NULL);
47a26690 1769
cc377381
LP
1770 do {
1771 free(id);
1772 id = NULL;
47a26690 1773
cc377381
LP
1774 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
1775 return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
47a26690 1776
cc377381 1777 } while (hashmap_get(m->inhibitors, id));
47a26690 1778
cc377381
LP
1779 r = manager_add_inhibitor(m, id, &i);
1780 if (r < 0)
1781 return sd_bus_reply_method_errno(bus, message, r, NULL);
47a26690 1782
cc377381
LP
1783 i->what = w;
1784 i->mode = mm;
1785 i->pid = pid;
1786 i->uid = uid;
1787 i->why = strdup(why);
1788 i->who = strdup(who);
7f7bb946 1789
cc377381
LP
1790 if (!i->why || !i->who) {
1791 r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
1792 goto fail;
1793 }
b668e064 1794
cc377381
LP
1795 fifo_fd = inhibitor_create_fifo(i);
1796 if (fifo_fd < 0) {
1797 r = sd_bus_reply_method_errno(bus, message, fifo_fd, NULL);
1798 goto fail;
1799 }
b668e064 1800
cc377381 1801 inhibitor_start(i);
b668e064 1802
cc377381 1803 return sd_bus_reply_method_return(bus, message, "h", fifo_fd);
b668e064 1804
cc377381
LP
1805fail:
1806 if (i)
1807 inhibitor_free(i);
89f13440 1808
cc377381
LP
1809 return r;
1810}
3f49d45a 1811
cc377381
LP
1812const sd_bus_vtable manager_vtable[] = {
1813 SD_BUS_VTABLE_START(0),
1814
1815 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), 0),
1816 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), 0),
1817 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), 0),
1818 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), 0),
1819 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1820 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1821 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1822 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1823 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
1824 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), 0),
1825 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), 0),
1826 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), 0),
1827 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), 0),
1828 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), 0),
1829 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), 0),
1830 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), 0),
1831 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
1832 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
1833
1834 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, 0),
1835 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, 0),
1836 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, 0),
1837 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, 0),
1838 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, 0),
1839 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, 0),
1840 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, 0),
1841 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, 0),
1842 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, 0),
1843 SD_BUS_METHOD("CreateSession", "uussssussbssa(sv)", "soshsub", method_create_session, 0),
1844 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
1845 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0),
1846 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, 0),
1847 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, 0),
1848 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, 0),
1849 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, 0),
1850 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, 0),
1851 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, 0),
1852 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, 0),
1853 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, 0),
1854 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, 0),
1855 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, 0),
1856 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, 0),
1857 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, 0),
1858 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, 0),
1859 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, 0),
1860 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, 0),
1861 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, 0),
1862 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, 0),
1863 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, 0),
1864 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, 0),
1865 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, 0),
1866 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, 0),
1867 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, 0),
1868 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, 0),
1869 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, 0),
1870
1871 SD_BUS_SIGNAL("SessionNew", "so", 0),
1872 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
1873 SD_BUS_SIGNAL("UserNew", "uo", 0),
1874 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
1875 SD_BUS_SIGNAL("SeatNew", "so", 0),
1876 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
1877 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
1878 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
1879
1880 SD_BUS_VTABLE_END
1881};
3f49d45a 1882
cc377381
LP
1883int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata) {
1884 const char *path, *result, *unit;
1885 Manager *m = userdata;
1886 Session *session;
1887 uint32_t id;
1888 User *user;
1889 int r;
3f49d45a 1890
cc377381
LP
1891 assert(bus);
1892 assert(message);
1893 assert(m);
3f49d45a 1894
cc377381
LP
1895 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
1896 if (r < 0) {
1897 log_error("Failed to parse JobRemoved message: %s", strerror(-r));
1898 return 0;
1899 }
3f49d45a 1900
cc377381
LP
1901 if (m->action_job && streq(m->action_job, path)) {
1902 log_info("Operation finished.");
3f49d45a 1903
cc377381
LP
1904 /* Tell people that they now may take a lock again */
1905 send_prepare_for(m, m->action_what, false);
3f49d45a 1906
cc377381
LP
1907 free(m->action_job);
1908 m->action_job = NULL;
1909 m->action_unit = NULL;
1910 m->action_what = 0;
1911 return 0;
1912 }
3f49d45a 1913
cc377381
LP
1914 session = hashmap_get(m->session_units, unit);
1915 if (session) {
3f49d45a 1916
cc377381
LP
1917 if (streq_ptr(path, session->scope_job)) {
1918 free(session->scope_job);
1919 session->scope_job = NULL;
3f49d45a
LP
1920 }
1921
cc377381
LP
1922 if (session->started) {
1923 if (streq(result, "done"))
1924 session_send_create_reply(session, NULL);
1925 else {
1926 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3f49d45a 1927
cc377381
LP
1928 sd_bus_error_setf(&error, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
1929 session_send_create_reply(session, &error);
1930 }
1931 } else
1932 session_save(session);
3f49d45a 1933
cc377381
LP
1934 session_add_to_gc_queue(session);
1935 }
3f49d45a 1936
cc377381
LP
1937 user = hashmap_get(m->user_units, unit);
1938 if (user) {
3f49d45a 1939
cc377381
LP
1940 if (streq_ptr(path, user->service_job)) {
1941 free(user->service_job);
1942 user->service_job = NULL;
3f49d45a
LP
1943 }
1944
cc377381
LP
1945 if (streq_ptr(path, user->slice_job)) {
1946 free(user->slice_job);
1947 user->slice_job = NULL;
1948 }
3f49d45a 1949
cc377381
LP
1950 user_save(user);
1951 user_add_to_gc_queue(user);
3f49d45a
LP
1952 }
1953
cc377381 1954 return 0;
3f49d45a
LP
1955}
1956
cc377381
LP
1957int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata) {
1958 const char *path, *unit;
1713813d 1959 Manager *m = userdata;
cc377381
LP
1960 Session *session;
1961 User *user;
1962 int r;
1713813d 1963
cc377381 1964 assert(bus);
1713813d 1965 assert(message);
cc377381 1966 assert(m);
1713813d 1967
cc377381
LP
1968 r = sd_bus_message_read(message, "so", &unit, &path);
1969 if (r < 0) {
1970 log_error("Failed to parse UnitRemoved message: %s", strerror(-r));
1971 return 0;
1972 }
fb6becb4 1973
cc377381
LP
1974 session = hashmap_get(m->session_units, unit);
1975 if (session)
1976 session_add_to_gc_queue(session);
fb6becb4 1977
cc377381
LP
1978 user = hashmap_get(m->user_units, unit);
1979 if (user)
1980 user_add_to_gc_queue(user);
fb6becb4 1981
cc377381
LP
1982 return 0;
1983}
fb6becb4 1984
cc377381
LP
1985int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
1986 _cleanup_free_ char *unit = NULL;
1987 Manager *m = userdata;
1988 const char *path;
1989 Session *session;
1990 User *user;
fb6becb4 1991
cc377381
LP
1992 assert(bus);
1993 assert(message);
1994 assert(m);
fb6becb4 1995
cc377381
LP
1996 path = sd_bus_message_get_path(message);
1997 if (!path)
1998 return 0;
fb6becb4 1999
cc377381
LP
2000 unit_name_from_dbus_path(path, &unit);
2001 if (!unit)
2002 return 0;
fb6becb4 2003
cc377381
LP
2004 session = hashmap_get(m->session_units, unit);
2005 if (session)
2006 session_add_to_gc_queue(session);
fb6becb4 2007
cc377381
LP
2008 user = hashmap_get(m->user_units, unit);
2009 if (user)
2010 user_add_to_gc_queue(user);
fb6becb4 2011
cc377381
LP
2012 return 0;
2013}
6fa48533 2014
cc377381
LP
2015int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata) {
2016 Manager *m = userdata;
2017 Session *session;
2018 Iterator i;
2019 int b, r;
943aca8e 2020
cc377381 2021 assert(bus);
943aca8e 2022
cc377381
LP
2023 r = sd_bus_message_read(message, "b", &b);
2024 if (r < 0) {
2025 log_error("Failed to parse Reloading message: %s", strerror(-r));
2026 return 0;
2027 }
943aca8e 2028
cc377381
LP
2029 if (b)
2030 return 0;
943aca8e 2031
cc377381
LP
2032 /* systemd finished reloading, let's recheck all our sessions */
2033 log_debug("System manager has been reloaded, rechecking sessions...");
6797c324 2034
cc377381
LP
2035 HASHMAP_FOREACH(session, m->sessions, i)
2036 session_add_to_gc_queue(session);
6797c324 2037
cc377381
LP
2038 return 0;
2039}
943aca8e 2040
cc377381
LP
2041int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
2042 const char *name, *old, *new;
2043 Manager *m = userdata;
2044 Session *session;
2045 Iterator i;
2046 int r;
943aca8e 2047
6797c324 2048
cc377381 2049 char *key;
e8b212fe 2050
cc377381
LP
2051 r = sd_bus_message_read(message, "sss", &name, &old, &new);
2052 if (r < 0) {
2053 log_error("Failed to parse NameOwnerChanged message: %s", strerror(-r));
2054 return 0;
2055 }
e8b212fe 2056
cc377381
LP
2057 if (isempty(old) || !isempty(new))
2058 return 0;
e8b212fe 2059
cc377381
LP
2060 key = set_remove(m->busnames, (char*) old);
2061 if (!key)
2062 return 0;
ae5e06bd 2063
cc377381 2064 /* Drop all controllers owned by this name */
ae5e06bd 2065
cc377381 2066 free(key);
1713813d 2067
cc377381
LP
2068 HASHMAP_FOREACH(session, m->sessions, i)
2069 if (session_is_controller(session, old))
2070 session_drop_controller(session);
1713813d 2071
cc377381 2072 return 0;
1713813d
LP
2073}
2074
cc377381
LP
2075int manager_send_changed(Manager *manager, const char *property, ...) {
2076 char **l;
9418f147
LP
2077
2078 assert(manager);
2079
cc377381 2080 l = strv_from_stdarg_alloca(property);
9418f147 2081
cc377381
LP
2082 return sd_bus_emit_properties_changed_strv(
2083 manager->bus,
2084 "/org/freedesktop/login1",
2085 "org.freedesktop.login1.Manager",
2086 l);
9418f147 2087}
eecd1362 2088
d889a206 2089int manager_dispatch_delayed(Manager *manager) {
cc377381 2090 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
eecd1362
LP
2091 int r;
2092
2093 assert(manager);
2094
84286536 2095 if (manager->action_what == 0 || manager->action_job)
eecd1362
LP
2096 return 0;
2097
2098 /* Continue delay? */
314b4b0a 2099 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0)) {
eecd1362 2100
314b4b0a
LP
2101 if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC))
2102 return 0;
af9792ac 2103
314b4b0a
LP
2104 log_info("Delay lock is active but inhibitor timeout is reached.");
2105 }
eecd1362 2106
314b4b0a 2107 /* Actually do the operation */
314b4b0a 2108 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
eecd1362 2109 if (r < 0) {
cc377381 2110 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
314b4b0a
LP
2111
2112 manager->action_unit = NULL;
2113 manager->action_what = 0;
eecd1362
LP
2114 return r;
2115 }
2116
eecd1362
LP
2117 return 1;
2118}
fb6becb4
LP
2119
2120int manager_start_scope(
2121 Manager *manager,
2122 const char *scope,
2123 pid_t pid,
2124 const char *slice,
2125 const char *description,
7fb3ee51 2126 const char *after,
405e0255 2127 const char *kill_mode,
cc377381 2128 sd_bus_error *error,
fb6becb4
LP
2129 char **job) {
2130
cc377381
LP
2131 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2132 int r;
fb6becb4
LP
2133
2134 assert(manager);
2135 assert(scope);
2136 assert(pid > 1);
2137
cc377381
LP
2138 r = sd_bus_message_new_method_call(
2139 manager->bus,
fb6becb4
LP
2140 "org.freedesktop.systemd1",
2141 "/org/freedesktop/systemd1",
2142 "org.freedesktop.systemd1.Manager",
cc377381
LP
2143 "StartTransientUnit",
2144 &m);
2145 if (r < 0)
2146 return r;
fb6becb4 2147
cc377381
LP
2148 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2149 if (r < 0)
2150 return r;
fb6becb4 2151
cc377381
LP
2152 r = sd_bus_message_open_container(m, 'a', "(sv)");
2153 if (r < 0)
2154 return r;
fb6becb4
LP
2155
2156 if (!isempty(slice)) {
cc377381
LP
2157 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2158 if (r < 0)
2159 return r;
fb6becb4
LP
2160 }
2161
2162 if (!isempty(description)) {
cc377381
LP
2163 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2164 if (r < 0)
2165 return r;
fb6becb4
LP
2166 }
2167
cc377381
LP
2168 if (!isempty(description)) {
2169 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2170 if (r < 0)
2171 return r;
7fb3ee51
LP
2172 }
2173
405e0255 2174 if (!isempty(kill_mode)) {
cc377381
LP
2175 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", kill_mode);
2176 if (r < 0)
2177 return r;
405e0255
LP
2178 }
2179
fb6becb4
LP
2180 /* cgroup empty notification is not available in containers
2181 * currently. To make this less problematic, let's shorten the
2182 * stop timeout for sessions, so that we don't wait
2183 * forever. */
2184
cc377381
LP
2185 r = sd_bus_message_append(m, "(sv)", "TimeoutStopUSec", "t", 500 * USEC_PER_MSEC);
2186 if (r < 0)
2187 return r;
fb6becb4 2188
743e8945
LP
2189 /* Make sure that the session shells are terminated with
2190 * SIGHUP since bash and friends tend to ignore SIGTERM */
cc377381
LP
2191 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2192 if (r < 0)
2193 return r;
2194
2195 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2196 if (r < 0)
2197 return r;
2198
2199 r = sd_bus_message_close_container(m);
2200 if (r < 0)
2201 return r;
2202
2203 r = sd_bus_send_with_reply_and_block(manager->bus, m, 0, error, &reply);
2204 if (r < 0)
2205 return r;
fb6becb4
LP
2206
2207 if (job) {
2208 const char *j;
2209 char *copy;
2210
cc377381
LP
2211 r = sd_bus_message_read(reply, "o", &j);
2212 if (r < 0)
2213 return r;
fb6becb4
LP
2214
2215 copy = strdup(j);
2216 if (!copy)
2217 return -ENOMEM;
2218
2219 *job = copy;
2220 }
2221
cc377381 2222 return 1;
fb6becb4
LP
2223}
2224
cc377381
LP
2225int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2226 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
fb6becb4
LP
2227 int r;
2228
2229 assert(manager);
2230 assert(unit);
2231
cc377381 2232 r = sd_bus_call_method(
fb6becb4
LP
2233 manager->bus,
2234 "org.freedesktop.systemd1",
2235 "/org/freedesktop/systemd1",
2236 "org.freedesktop.systemd1.Manager",
2237 "StartUnit",
fb6becb4 2238 error,
cc377381
LP
2239 &reply,
2240 "ss", unit, "fail");
2241 if (r < 0)
fb6becb4 2242 return r;
fb6becb4
LP
2243
2244 if (job) {
2245 const char *j;
2246 char *copy;
2247
cc377381
LP
2248 r = sd_bus_message_read(reply, "o", &j);
2249 if (r < 0)
2250 return r;
fb6becb4
LP
2251
2252 copy = strdup(j);
2253 if (!copy)
2254 return -ENOMEM;
2255
2256 *job = copy;
2257 }
2258
cc377381 2259 return 1;
fb6becb4
LP
2260}
2261
cc377381
LP
2262int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2263 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
fb6becb4
LP
2264 int r;
2265
2266 assert(manager);
2267 assert(unit);
2268
cc377381 2269 r = sd_bus_call_method(
fb6becb4
LP
2270 manager->bus,
2271 "org.freedesktop.systemd1",
2272 "/org/freedesktop/systemd1",
2273 "org.freedesktop.systemd1.Manager",
2274 "StopUnit",
fb6becb4 2275 error,
cc377381
LP
2276 &reply,
2277 "ss", unit, "fail");
fb6becb4 2278 if (r < 0) {
cc377381
LP
2279 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
2280 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
6797c324
LP
2281
2282 if (job)
2283 *job = NULL;
2284
cc377381 2285 sd_bus_error_free(error);
6797c324
LP
2286 return 0;
2287 }
2288
fb6becb4
LP
2289 return r;
2290 }
2291
2292 if (job) {
2293 const char *j;
2294 char *copy;
2295
cc377381
LP
2296 r = sd_bus_message_read(reply, "o", &j);
2297 if (r < 0)
2298 return r;
fb6becb4
LP
2299
2300 copy = strdup(j);
2301 if (!copy)
2302 return -ENOMEM;
2303
2304 *job = copy;
2305 }
2306
6797c324 2307 return 1;
fb6becb4
LP
2308}
2309
cc377381 2310int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
fb6becb4
LP
2311 assert(manager);
2312 assert(unit);
2313
cc377381 2314 return sd_bus_call_method(
fb6becb4
LP
2315 manager->bus,
2316 "org.freedesktop.systemd1",
2317 "/org/freedesktop/systemd1",
2318 "org.freedesktop.systemd1.Manager",
2319 "KillUnit",
fb6becb4 2320 error,
cc377381
LP
2321 NULL,
2322 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
fb6becb4
LP
2323}
2324
2325int manager_unit_is_active(Manager *manager, const char *unit) {
cc377381
LP
2326 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2327 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
fb6becb4 2328 _cleanup_free_ char *path = NULL;
fb6becb4 2329 const char *state;
fb6becb4
LP
2330 int r;
2331
2332 assert(manager);
2333 assert(unit);
2334
fb6becb4
LP
2335 path = unit_dbus_path_from_name(unit);
2336 if (!path)
2337 return -ENOMEM;
2338
cc377381 2339 r = sd_bus_get_property(
fb6becb4
LP
2340 manager->bus,
2341 "org.freedesktop.systemd1",
2342 path,
cc377381
LP
2343 "org.freedesktop.systemd1.Unit",
2344 "ActiveState",
fb6becb4 2345 &error,
cc377381
LP
2346 &reply,
2347 "s");
fb6becb4 2348 if (r < 0) {
cc377381
LP
2349 /* systemd might have droppped off momentarily, let's
2350 * not make this an error */
2351 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2352 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
6797c324 2353 return true;
6797c324 2354
cc377381
LP
2355 /* If the unit is already unloaded then it's not
2356 * active */
2357 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
2358 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
6797c324 2359 return false;
6797c324 2360
fb6becb4
LP
2361 return r;
2362 }
2363
cc377381
LP
2364 r = sd_bus_message_read(reply, "s", &state);
2365 if (r < 0)
fb6becb4 2366 return -EINVAL;
fb6becb4 2367
cc377381
LP
2368 return !streq(state, "inactive") && !streq(state, "failed");
2369}
2370
2371int manager_job_is_active(Manager *manager, const char *path) {
2372 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2373 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2374 int r;
2375
2376 assert(manager);
2377 assert(path);
2378
2379 r = sd_bus_get_property(
2380 manager->bus,
2381 "org.freedesktop.systemd1",
2382 path,
2383 "org.freedesktop.systemd1.Job",
2384 "State",
2385 &error,
2386 &reply,
2387 "s");
2388 if (r < 0) {
2389 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
2390 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
2391 return true;
2392
2393 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
2394 return false;
2395
2396 return r;
fb6becb4
LP
2397 }
2398
cc377381
LP
2399 /* We don't actually care about the state really. The fact
2400 * that we could read the job state is enough for us */
fb6becb4 2401
cc377381 2402 return true;
fb6becb4 2403}