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