]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-core.c
Merge pull request #30513 from rpigott/resolved-ede
[thirdparty/systemd.git] / src / login / logind-core.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2b3ab29d 2
2b3ab29d 3#include <fcntl.h>
cf0fbc49
TA
4#include <sys/ioctl.h>
5#include <sys/types.h>
2b3ab29d
ZJS
6#include <linux/vt.h>
7
4f209af7
YW
8#include "sd-device.h"
9
b5efdb8a 10#include "alloc-util.h"
af4e8e86 11#include "battery-util.h"
cc377381 12#include "bus-error.h"
59228d0d 13#include "bus-locator.h"
3ffd4af2
LP
14#include "bus-util.h"
15#include "cgroup-util.h"
ae98d374 16#include "conf-parser.h"
8437c059 17#include "device-util.h"
d4bd786d 18#include "efi-loader.h"
66855de7 19#include "errno-util.h"
3ffd4af2 20#include "fd-util.h"
eefc66aa 21#include "limits-util.h"
cc377381 22#include "logind.h"
c29b65f7 23#include "parse-util.h"
3d0ef5c7 24#include "path-util.h"
dccca82b 25#include "process-util.h"
d7a0f1f4 26#include "stdio-util.h"
3ffd4af2 27#include "strv.h"
288a74cc 28#include "terminal-util.h"
91bd2c34 29#include "udev-util.h"
b1d4f8e1 30#include "user-util.h"
22c902fa 31#include "userdb.h"
c2a99093 32#include "utmp-wtmp.h"
2b3ab29d 33
ae98d374 34void manager_reset_config(Manager *m) {
23462168
LP
35 assert(m);
36
ae98d374
ZJS
37 m->n_autovts = 6;
38 m->reserve_vt = 6;
39 m->remove_ipc = true;
40 m->inhibit_delay_max = 5 * USEC_PER_SEC;
9afe9efb
LP
41 m->user_stop_delay = 10 * USEC_PER_SEC;
42
cd4dd90b
MY
43 m->handle_action_sleep_mask = HANDLE_ACTION_SLEEP_MASK_DEFAULT;
44
ae98d374 45 m->handle_power_key = HANDLE_POWEROFF;
a520bb66
YA
46 m->handle_power_key_long_press = HANDLE_IGNORE;
47 m->handle_reboot_key = HANDLE_REBOOT;
48 m->handle_reboot_key_long_press = HANDLE_POWEROFF;
ae98d374 49 m->handle_suspend_key = HANDLE_SUSPEND;
a520bb66 50 m->handle_suspend_key_long_press = HANDLE_HIBERNATE;
ae98d374 51 m->handle_hibernate_key = HANDLE_HIBERNATE;
a520bb66
YA
52 m->handle_hibernate_key_long_press = HANDLE_IGNORE;
53
ae98d374
ZJS
54 m->handle_lid_switch = HANDLE_SUSPEND;
55 m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
56 m->handle_lid_switch_docked = HANDLE_IGNORE;
a520bb66 57
ae98d374
ZJS
58 m->power_key_ignore_inhibited = false;
59 m->suspend_key_ignore_inhibited = false;
60 m->hibernate_key_ignore_inhibited = false;
61 m->lid_switch_ignore_inhibited = true;
adbb2b6a 62 m->reboot_key_ignore_inhibited = false;
ae98d374
ZJS
63
64 m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
65
66 m->idle_action_usec = 30 * USEC_PER_MINUTE;
67 m->idle_action = HANDLE_IGNORE;
68
69 m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
cc1c85fb 70 m->runtime_dir_inodes = DIV_ROUND_UP(m->runtime_dir_size, 4096); /* 4k per inode */
ae98d374
ZJS
71 m->sessions_max = 8192;
72 m->inhibitors_max = 8192;
73
74 m->kill_user_processes = KILL_USER_PROCESSES;
75
76 m->kill_only_users = strv_free(m->kill_only_users);
77 m->kill_exclude_users = strv_free(m->kill_exclude_users);
82325af3
MS
78
79 m->stop_idle_session_usec = USEC_INFINITY;
ae98d374
ZJS
80}
81
82int manager_parse_config_file(Manager *m) {
83 assert(m);
84
07e0ffc8
FB
85 return config_parse_config_file("logind.conf", "Login\0",
86 config_item_perf_lookup, logind_gperf_lookup,
87 CONFIG_PARSE_WARN, m);
ae98d374
ZJS
88}
89
f68d1485 90int manager_add_device(Manager *m, const char *sysfs, bool master, Device **ret_device) {
2b3ab29d
ZJS
91 Device *d;
92
93 assert(m);
94 assert(sysfs);
95
96 d = hashmap_get(m->devices, sysfs);
61376f96 97 if (d)
2b3ab29d
ZJS
98 /* we support adding master-flags, but not removing them */
99 d->master = d->master || master;
61376f96
ZJS
100 else {
101 d = device_new(m, sysfs, master);
102 if (!d)
103 return -ENOMEM;
2b3ab29d
ZJS
104 }
105
f68d1485
ZJS
106 if (ret_device)
107 *ret_device = d;
2b3ab29d
ZJS
108
109 return 0;
110}
111
f68d1485 112int manager_add_seat(Manager *m, const char *id, Seat **ret_seat) {
2b3ab29d 113 Seat *s;
8c29a457 114 int r;
2b3ab29d
ZJS
115
116 assert(m);
117 assert(id);
118
119 s = hashmap_get(m->seats, id);
61376f96 120 if (!s) {
8c29a457
LP
121 r = seat_new(&s, m, id);
122 if (r < 0)
123 return r;
2b3ab29d
ZJS
124 }
125
f68d1485
ZJS
126 if (ret_seat)
127 *ret_seat = s;
2b3ab29d
ZJS
128
129 return 0;
130}
131
f68d1485 132int manager_add_session(Manager *m, const char *id, Session **ret_session) {
2b3ab29d 133 Session *s;
8c29a457 134 int r;
2b3ab29d
ZJS
135
136 assert(m);
137 assert(id);
138
139 s = hashmap_get(m->sessions, id);
61376f96 140 if (!s) {
8c29a457
LP
141 r = session_new(&s, m, id);
142 if (r < 0)
143 return r;
2b3ab29d
ZJS
144 }
145
f68d1485
ZJS
146 if (ret_session)
147 *ret_session = s;
2b3ab29d
ZJS
148
149 return 0;
150}
151
d5ac9d06
LP
152int manager_add_user(
153 Manager *m,
22c902fa 154 UserRecord *ur,
f68d1485 155 User **ret_user) {
d5ac9d06 156
2b3ab29d 157 User *u;
157f5057 158 int r;
2b3ab29d
ZJS
159
160 assert(m);
22c902fa 161 assert(ur);
2b3ab29d 162
22c902fa 163 u = hashmap_get(m->users, UID_TO_PTR(ur->uid));
61376f96 164 if (!u) {
22c902fa 165 r = user_new(&u, m, ur);
157f5057
DH
166 if (r < 0)
167 return r;
2b3ab29d
ZJS
168 }
169
f68d1485
ZJS
170 if (ret_user)
171 *ret_user = u;
2b3ab29d
ZJS
172
173 return 0;
174}
175
d5ac9d06
LP
176int manager_add_user_by_name(
177 Manager *m,
178 const char *name,
f68d1485 179 User **ret_user) {
d5ac9d06 180
22c902fa 181 _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
2b3ab29d
ZJS
182 int r;
183
184 assert(m);
185 assert(name);
186
80d88a82 187 r = userdb_by_name(name, USERDB_SUPPRESS_SHADOW, &ur);
2b3ab29d
ZJS
188 if (r < 0)
189 return r;
190
22c902fa 191 return manager_add_user(m, ur, ret_user);
2b3ab29d
ZJS
192}
193
22c902fa
LP
194int manager_add_user_by_uid(
195 Manager *m,
196 uid_t uid,
197 User **ret_user) {
198
199 _cleanup_(user_record_unrefp) UserRecord *ur = NULL;
200 int r;
2b3ab29d
ZJS
201
202 assert(m);
22c902fa 203 assert(uid_is_valid(uid));
2b3ab29d 204
80d88a82 205 r = userdb_by_uid(uid, USERDB_SUPPRESS_SHADOW, &ur);
22c902fa
LP
206 if (r < 0)
207 return r;
2b3ab29d 208
22c902fa 209 return manager_add_user(m, ur, ret_user);
2b3ab29d
ZJS
210}
211
81280b2a 212int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret) {
2b3ab29d 213 Inhibitor *i;
81280b2a 214 int r;
2b3ab29d
ZJS
215
216 assert(m);
217 assert(id);
218
219 i = hashmap_get(m->inhibitors, id);
81280b2a
LP
220 if (!i) {
221 r = inhibitor_new(&i, m, id);
222 if (r < 0)
223 return r;
2b3ab29d
ZJS
224 }
225
81280b2a
LP
226 if (ret)
227 *ret = i;
2b3ab29d
ZJS
228
229 return 0;
230}
231
f68d1485 232int manager_add_button(Manager *m, const char *name, Button **ret_button) {
2b3ab29d
ZJS
233 Button *b;
234
235 assert(m);
236 assert(name);
237
238 b = hashmap_get(m->buttons, name);
61376f96
ZJS
239 if (!b) {
240 b = button_new(m, name);
241 if (!b)
242 return -ENOMEM;
2b3ab29d
ZJS
243 }
244
f68d1485
ZJS
245 if (ret_button)
246 *ret_button = b;
2b3ab29d
ZJS
247
248 return 0;
249}
250
4f209af7 251int manager_process_seat_device(Manager *m, sd_device *d) {
2b3ab29d
ZJS
252 Device *device;
253 int r;
254
255 assert(m);
256
a1130022 257 if (device_for_action(d, SD_DEVICE_REMOVE) ||
643bb924 258 sd_device_has_current_tag(d, "seat") <= 0) {
4f209af7
YW
259 const char *syspath;
260
261 r = sd_device_get_syspath(d, &syspath);
262 if (r < 0)
263 return 0;
2b3ab29d 264
4f209af7 265 device = hashmap_get(m->devices, syspath);
2b3ab29d
ZJS
266 if (!device)
267 return 0;
268
269 seat_add_to_gc_queue(device->seat);
270 device_free(device);
271
272 } else {
4f209af7 273 const char *sn, *syspath;
2b3ab29d 274 bool master;
4f209af7 275 Seat *seat;
2b3ab29d 276
4f209af7 277 if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn))
2b3ab29d
ZJS
278 sn = "seat0";
279
280 if (!seat_name_is_valid(sn)) {
76386309 281 log_device_warning(d, "Device with invalid seat name %s found, ignoring.", sn);
2b3ab29d
ZJS
282 return 0;
283 }
284
6a79c586 285 seat = hashmap_get(m->seats, sn);
643bb924 286 master = sd_device_has_current_tag(d, "master-of-seat") > 0;
6a79c586
LP
287
288 /* Ignore non-master devices for unknown seats */
289 if (!master && !seat)
2b3ab29d
ZJS
290 return 0;
291
4f209af7
YW
292 r = sd_device_get_syspath(d, &syspath);
293 if (r < 0)
294 return r;
295
296 r = manager_add_device(m, syspath, master, &device);
2b3ab29d
ZJS
297 if (r < 0)
298 return r;
299
300 if (!seat) {
301 r = manager_add_seat(m, sn, &seat);
302 if (r < 0) {
303 if (!device->seat)
304 device_free(device);
305
306 return r;
307 }
308 }
309
310 device_attach(device, seat);
311 seat_start(seat);
312 }
313
314 return 0;
315}
316
4f209af7 317int manager_process_button_device(Manager *m, sd_device *d) {
91bd2c34 318 const char *sysname;
2b3ab29d 319 Button *b;
2b3ab29d
ZJS
320 int r;
321
322 assert(m);
323
4f209af7
YW
324 r = sd_device_get_sysname(d, &sysname);
325 if (r < 0)
326 return r;
327
a1130022 328 if (device_for_action(d, SD_DEVICE_REMOVE) ||
3d01bfa7 329 sd_device_has_current_tag(d, "power-switch") <= 0)
2b3ab29d 330
3d01bfa7 331 button_free(hashmap_get(m->buttons, sysname));
2b3ab29d 332
3d01bfa7 333 else {
c679e12a 334 const char *sn;
2b3ab29d 335
4f209af7 336 r = manager_add_button(m, sysname, &b);
2b3ab29d
ZJS
337 if (r < 0)
338 return r;
339
4f209af7 340 if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn))
2b3ab29d
ZJS
341 sn = "seat0";
342
343 button_set_seat(b, sn);
2546b70a
LP
344
345 r = button_open(b);
346 if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error
347 * opening the device?) let's close the button again. */
348 button_free(b);
2b3ab29d
ZJS
349 }
350
351 return 0;
352}
353
8494f562 354int manager_get_session_by_pidref(Manager *m, const PidRef *pid, Session **ret) {
2b3ab29d
ZJS
355 _cleanup_free_ char *unit = NULL;
356 Session *s;
357 int r;
358
359 assert(m);
2b3ab29d 360
8494f562 361 if (!pidref_is_set(pid))
2b3ab29d
ZJS
362 return -EINVAL;
363
8494f562
MY
364 s = hashmap_get(m->sessions_by_leader, pid);
365 if (s) {
366 r = pidref_verify(pid);
367 if (r < 0)
368 return r;
369 } else {
370 r = cg_pidref_get_unit(pid, &unit);
371 if (r < 0)
372 return r;
373
374 s = hashmap_get(m->session_units, unit);
238794b1 375 }
14ef4a65
LP
376
377 if (ret)
378 *ret = s;
2b3ab29d 379
c9ee7160 380 return !!s;
2b3ab29d
ZJS
381}
382
14ef4a65 383int manager_get_user_by_pid(Manager *m, pid_t pid, User **ret) {
2b3ab29d 384 _cleanup_free_ char *unit = NULL;
c9ee7160 385 User *u = NULL;
2b3ab29d
ZJS
386 int r;
387
388 assert(m);
2b3ab29d 389
6f876815 390 if (!pid_is_valid(pid))
2b3ab29d
ZJS
391 return -EINVAL;
392
393 r = cg_pid_get_slice(pid, &unit);
c9ee7160
ZJS
394 if (r >= 0)
395 u = hashmap_get(m->user_units, unit);
14ef4a65
LP
396
397 if (ret)
398 *ret = u;
2b3ab29d 399
c9ee7160 400 return !!u;
2b3ab29d
ZJS
401}
402
403int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
404 Session *s;
405 bool idle_hint;
5cb14b37 406 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
2b3ab29d
ZJS
407
408 assert(m);
409
85a428c6 410 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
2b3ab29d 411
90e74a66 412 HASHMAP_FOREACH(s, m->sessions) {
2b3ab29d
ZJS
413 dual_timestamp k;
414 int ih;
415
416 ih = session_get_idle_hint(s, &k);
417 if (ih < 0)
418 return ih;
419
420 if (!ih) {
421 if (!idle_hint) {
422 if (k.monotonic < ts.monotonic)
423 ts = k;
424 } else {
425 idle_hint = false;
426 ts = k;
427 }
428 } else if (idle_hint) {
429
430 if (k.monotonic > ts.monotonic)
431 ts = k;
432 }
433 }
434
435 if (t)
436 *t = ts;
437
438 return idle_hint;
439}
440
441bool manager_shall_kill(Manager *m, const char *user) {
442 assert(m);
443 assert(user);
444
a2ed7077
ZJS
445 if (!m->kill_exclude_users && streq(user, "root"))
446 return false;
447
2b3ab29d
ZJS
448 if (strv_contains(m->kill_exclude_users, user))
449 return false;
450
921f831d
ZJS
451 if (!strv_isempty(m->kill_only_users))
452 return strv_contains(m->kill_only_users, user);
2b3ab29d 453
921f831d 454 return m->kill_user_processes;
2b3ab29d
ZJS
455}
456
c29b65f7
AJ
457int config_parse_n_autovts(
458 const char *unit,
459 const char *filename,
460 unsigned line,
461 const char *section,
462 unsigned section_line,
463 const char *lvalue,
464 int ltype,
465 const char *rvalue,
466 void *data,
467 void *userdata) {
468
99534007 469 unsigned *n = ASSERT_PTR(data);
c29b65f7
AJ
470 unsigned o;
471 int r;
472
473 assert(filename);
474 assert(lvalue);
475 assert(rvalue);
c29b65f7
AJ
476
477 r = safe_atou(rvalue, &o);
478 if (r < 0) {
196d41bc
YW
479 log_syntax(unit, LOG_WARNING, filename, line, r,
480 "Failed to parse number of autovts, ignoring: %s", rvalue);
c29b65f7
AJ
481 return 0;
482 }
483
484 if (o > 15) {
196d41bc
YW
485 log_syntax(unit, LOG_WARNING, filename, line, 0,
486 "A maximum of 15 autovts are supported, ignoring: %s", rvalue);
c29b65f7
AJ
487 return 0;
488 }
489
490 *n = o;
491 return 0;
492}
493
14cb109d 494static int vt_is_busy(unsigned vtnr) {
2b3ab29d 495 struct vt_stat vt_stat;
6d95e7d9 496 int r;
254d1313 497 _cleanup_close_ int fd = -EBADF;
2b3ab29d
ZJS
498
499 assert(vtnr >= 1);
500
c29b65f7
AJ
501 /* VT_GETSTATE "cannot return state for more than 16 VTs, since v_state is short" */
502 assert(vtnr <= 15);
503
2b3ab29d
ZJS
504 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
505 * we'd open the latter we'd open the foreground tty which
506 * hence would be unconditionally busy. By opening /dev/tty1
507 * we avoid this. Since tty1 is special and needs to be an
508 * explicitly loaded getty or DM this is safe. */
509
510 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
511 if (fd < 0)
512 return -errno;
513
514 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
515 r = -errno;
516 else
517 r = !!(vt_stat.v_state & (1 << vtnr));
518
2b3ab29d
ZJS
519 return r;
520}
521
14cb109d 522int manager_spawn_autovt(Manager *m, unsigned vtnr) {
4afd3348 523 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
14cb109d 524 char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned)];
2b3ab29d 525 int r;
2b3ab29d
ZJS
526
527 assert(m);
528 assert(vtnr >= 1);
529
92bd5ff3
DH
530 if (vtnr > m->n_autovts &&
531 vtnr != m->reserve_vt)
2b3ab29d
ZJS
532 return 0;
533
92bd5ff3 534 if (vtnr != m->reserve_vt) {
2b3ab29d
ZJS
535 /* If this is the reserved TTY, we'll start the getty
536 * on it in any case, but otherwise only if it is not
537 * busy. */
538
539 r = vt_is_busy(vtnr);
540 if (r < 0)
541 return r;
542 else if (r > 0)
543 return -EBUSY;
544 }
545
d7a0f1f4 546 xsprintf(name, "autovt@tty%u.service", vtnr);
59228d0d 547 r = bus_call_method(m->bus, bus_systemd_mgr, "StartUnit", &error, NULL, "ss", name, "fail");
cc377381 548 if (r < 0)
4ae25393 549 return log_error_errno(r, "Failed to start %s: %s", name, bus_error_message(&error, r));
2b3ab29d 550
4ae25393 551 return 0;
2b3ab29d 552}
2d62c530 553
9b9c23da 554bool manager_is_lid_closed(Manager *m) {
9b9c23da
LP
555 Button *b;
556
90e74a66 557 HASHMAP_FOREACH(b, m->buttons)
9b9c23da
LP
558 if (b->lid_closed)
559 return true;
560
561 return false;
562}
563
602a41c2 564static bool manager_is_docked(Manager *m) {
2d62c530
LP
565 Button *b;
566
90e74a66 567 HASHMAP_FOREACH(b, m->buttons)
2d62c530
LP
568 if (b->docked)
569 return true;
570
571 return false;
572}
6a79c586 573
602a41c2 574static int manager_count_external_displays(Manager *m) {
4f209af7 575 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
4f209af7 576 int r, n = 0;
6a79c586 577
4f209af7
YW
578 r = sd_device_enumerator_new(&e);
579 if (r < 0)
580 return r;
6a79c586 581
4f209af7 582 r = sd_device_enumerator_allow_uninitialized(e);
6a79c586
LP
583 if (r < 0)
584 return r;
585
4f209af7 586 r = sd_device_enumerator_add_match_subsystem(e, "drm", true);
6a79c586
LP
587 if (r < 0)
588 return r;
589
8437c059 590 FOREACH_DEVICE(e, d) {
fb53ee0a 591 const char *status, *enabled, *dash, *nn;
4f209af7 592 sd_device *p;
6a79c586 593
4f209af7 594 if (sd_device_get_parent(d, &p) < 0)
94036de8 595 continue;
6a79c586
LP
596
597 /* If the parent shares the same subsystem as the
598 * device we are looking at then it is a connector,
599 * which is what we are interested in. */
fb53ee0a 600 if (!device_in_subsystem(p, "drm"))
6a79c586
LP
601 continue;
602
4f209af7 603 if (sd_device_get_sysname(d, &nn) < 0)
602a41c2
LP
604 continue;
605
6b000af4
LP
606 /* Ignore internal displays: the type is encoded in the sysfs name, as the second dash
607 * separated item (the first is the card name, the last the connector number). We implement a
608 * deny list of external displays here, rather than an allow list of internal ones, to ensure
609 * we don't block suspends too eagerly. */
602a41c2
LP
610 dash = strchr(nn, '-');
611 if (!dash)
612 continue;
613
614 dash++;
49fe5c09
LP
615 if (!STARTSWITH_SET(dash,
616 "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
617 "Composite-", "SVIDEO-", "Component-",
618 "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-"))
602a41c2
LP
619 continue;
620
621 /* Ignore ports that are not enabled */
4f209af7 622 if (sd_device_get_sysattr_value(d, "enabled", &enabled) < 0 || !streq(enabled, "enabled"))
602a41c2
LP
623 continue;
624
6a79c586
LP
625 /* We count any connector which is not explicitly
626 * "disconnected" as connected. */
4f209af7 627 if (sd_device_get_sysattr_value(d, "status", &status) < 0 || !streq(status, "disconnected"))
6a79c586
LP
628 n++;
629 }
630
631 return n;
632}
3c56cab4 633
602a41c2 634bool manager_is_docked_or_external_displays(Manager *m) {
3c56cab4
BW
635 int n;
636
637 /* If we are docked don't react to lid closing */
638 if (manager_is_docked(m)) {
639 log_debug("System is docked.");
640 return true;
641 }
642
643 /* If we have more than one display connected,
644 * assume that we are docked. */
602a41c2 645 n = manager_count_external_displays(m);
3c56cab4 646 if (n < 0)
da927ba9 647 log_warning_errno(n, "Display counting failed: %m");
602a41c2
LP
648 else if (n >= 1) {
649 log_debug("External (%i) displays connected.", n);
3c56cab4
BW
650 return true;
651 }
652
653 return false;
654}
e25937a3
SF
655
656bool manager_is_on_external_power(void) {
657 int r;
658
e455380b
LP
659 /* For now we only check for AC power, but 'external power' can apply to anything that isn't an internal
660 * battery */
e25937a3
SF
661 r = on_ac_power();
662 if (r < 0)
663 log_warning_errno(r, "Failed to read AC power status: %m");
e25937a3 664
e455380b 665 return r != 0; /* Treat failure as 'on AC' */
e25937a3
SF
666}
667
668bool manager_all_buttons_ignored(Manager *m) {
864fe630
LP
669 assert(m);
670
e25937a3
SF
671 if (m->handle_power_key != HANDLE_IGNORE)
672 return false;
a520bb66
YA
673 if (m->handle_power_key_long_press != HANDLE_IGNORE)
674 return false;
e25937a3
SF
675 if (m->handle_suspend_key != HANDLE_IGNORE)
676 return false;
a520bb66
YA
677 if (m->handle_suspend_key_long_press != HANDLE_IGNORE)
678 return false;
e25937a3
SF
679 if (m->handle_hibernate_key != HANDLE_IGNORE)
680 return false;
a520bb66
YA
681 if (m->handle_hibernate_key_long_press != HANDLE_IGNORE)
682 return false;
683 if (m->handle_reboot_key != HANDLE_IGNORE)
684 return false;
685 if (m->handle_reboot_key_long_press != HANDLE_IGNORE)
686 return false;
e25937a3
SF
687 if (m->handle_lid_switch != HANDLE_IGNORE)
688 return false;
ed0cb346 689 if (!IN_SET(m->handle_lid_switch_ep, _HANDLE_ACTION_INVALID, HANDLE_IGNORE))
e25937a3
SF
690 return false;
691 if (m->handle_lid_switch_docked != HANDLE_IGNORE)
692 return false;
864fe630 693
e25937a3
SF
694 return true;
695}
3d0ef5c7
LP
696
697int manager_read_utmp(Manager *m) {
698#if ENABLE_UTMP
699 int r;
d7ac0952 700 _unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
3d0ef5c7
LP
701
702 assert(m);
703
704 if (utmpxname(_PATH_UTMPX) < 0)
705 return log_error_errno(errno, "Failed to set utmp path to " _PATH_UTMPX ": %m");
706
c2a99093 707 utmpx = utxent_start();
3d0ef5c7
LP
708
709 for (;;) {
710 _cleanup_free_ char *t = NULL;
711 struct utmpx *u;
712 const char *c;
713 Session *s;
714
715 errno = 0;
716 u = getutxent();
717 if (!u) {
9830d716
LP
718 if (errno == ENOENT)
719 log_debug_errno(errno, _PATH_UTMPX " does not exist, ignoring.");
720 else if (errno != 0)
3d0ef5c7 721 log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m");
c2a99093 722 return 0;
3d0ef5c7
LP
723 }
724
725 if (u->ut_type != USER_PROCESS)
726 continue;
727
728 if (!pid_is_valid(u->ut_pid))
729 continue;
730
731 t = strndup(u->ut_line, sizeof(u->ut_line));
c2a99093
ZJS
732 if (!t)
733 return log_oom();
3d0ef5c7
LP
734
735 c = path_startswith(t, "/dev/");
736 if (c) {
737 r = free_and_strdup(&t, c);
c2a99093
ZJS
738 if (r < 0)
739 return log_oom();
3d0ef5c7
LP
740 }
741
742 if (isempty(t))
743 continue;
744
8494f562 745 if (manager_get_session_by_pidref(m, &PIDREF_MAKE_FROM_PID(u->ut_pid), &s) <= 0)
3d0ef5c7
LP
746 continue;
747
748 if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) {
749 /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In
750 * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY
751 * information and never acquire it again. */
752
753 s->tty = mfree(s->tty);
754 s->tty_validity = TTY_UTMP_INCONSISTENT;
755 log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id);
756 continue;
757 }
758
759 /* Never override what we figured out once */
760 if (s->tty || s->tty_validity >= 0)
761 continue;
762
763 s->tty = TAKE_PTR(t);
764 s->tty_validity = TTY_FROM_UTMP;
765 log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
766 }
767
3d0ef5c7 768#else
86cf4554 769 return 0;
3d0ef5c7
LP
770#endif
771}
772
773#if ENABLE_UTMP
774static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) {
99534007 775 Manager *m = ASSERT_PTR(userdata);
3d0ef5c7
LP
776
777 /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's
778 * reestablish the watch on whatever there's now. */
779 if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0)
780 manager_connect_utmp(m);
781
782 (void) manager_read_utmp(m);
783 return 0;
784}
785#endif
786
787void manager_connect_utmp(Manager *m) {
788#if ENABLE_UTMP
789 sd_event_source *s = NULL;
790 int r;
791
792 assert(m);
793
794 /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM
795 * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known
796 * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and
797 * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry.
798 *
799 * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle
800 * detection (which, for tty sessions, relies on the TTY used) */
801
802 r = sd_event_add_inotify(m->event, &s, _PATH_UTMPX, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m);
803 if (r < 0)
804 log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " _PATH_UTMPX ", ignoring: %m");
805 else {
806 r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
807 if (r < 0)
808 log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m");
809
810 (void) sd_event_source_set_description(s, "utmp");
811 }
812
813 sd_event_source_unref(m->utmp_event_source);
814 m->utmp_event_source = s;
815#endif
816}
817
818void manager_reconnect_utmp(Manager *m) {
819#if ENABLE_UTMP
820 assert(m);
821
822 if (m->utmp_event_source)
823 return;
824
825 manager_connect_utmp(m);
826#endif
827}
d4bd786d
LP
828
829int manager_read_efi_boot_loader_entries(Manager *m) {
830#if ENABLE_EFI
831 int r;
832
833 assert(m);
834 if (m->efi_boot_loader_entries_set)
835 return 0;
836
837 r = efi_loader_get_entries(&m->efi_boot_loader_entries);
1209bf75
DL
838 if (r < 0) {
839 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r)) {
840 log_debug_errno(r, "Boot loader reported no entries.");
841 m->efi_boot_loader_entries_set = true;
842 return 0;
843 }
d4bd786d 844 return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
1209bf75 845 }
d4bd786d
LP
846
847 m->efi_boot_loader_entries_set = true;
848 return 1;
849#else
850 return 0;
851#endif
852}