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