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