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