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