]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-core.c
Merge pull request #20157 from keszybz/numerical-uids-in--M
[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
76 int manager_parse_config_file(Manager *m) {
77 assert(m);
78
79 return config_parse_many_nulstr(
80 PKGSYSCONFDIR "/logind.conf",
81 CONF_PATHS_NULSTR("systemd/logind.conf.d"),
82 "Login\0",
83 config_item_perf_lookup, logind_gperf_lookup,
84 CONFIG_PARSE_WARN, m,
85 NULL);
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 b = hashmap_get(m->buttons, sysname);
330 if (!b)
331 return 0;
332
333 button_free(b);
334
335 } else {
336 const char *sn;
337
338 r = manager_add_button(m, sysname, &b);
339 if (r < 0)
340 return r;
341
342 if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn))
343 sn = "seat0";
344
345 button_set_seat(b, sn);
346
347 r = button_open(b);
348 if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error
349 * opening the device?) let's close the button again. */
350 button_free(b);
351 }
352
353 return 0;
354 }
355
356 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **ret) {
357 _cleanup_free_ char *unit = NULL;
358 Session *s;
359 int r;
360
361 assert(m);
362
363 if (!pid_is_valid(pid))
364 return -EINVAL;
365
366 s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(pid));
367 if (!s) {
368 r = cg_pid_get_unit(pid, &unit);
369 if (r >= 0)
370 s = hashmap_get(m->session_units, unit);
371 }
372
373 if (ret)
374 *ret = s;
375
376 return !!s;
377 }
378
379 int manager_get_user_by_pid(Manager *m, pid_t pid, User **ret) {
380 _cleanup_free_ char *unit = NULL;
381 User *u = NULL;
382 int r;
383
384 assert(m);
385
386 if (!pid_is_valid(pid))
387 return -EINVAL;
388
389 r = cg_pid_get_slice(pid, &unit);
390 if (r >= 0)
391 u = hashmap_get(m->user_units, unit);
392
393 if (ret)
394 *ret = u;
395
396 return !!u;
397 }
398
399 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
400 Session *s;
401 bool idle_hint;
402 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
403
404 assert(m);
405
406 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
407
408 HASHMAP_FOREACH(s, m->sessions) {
409 dual_timestamp k;
410 int ih;
411
412 ih = session_get_idle_hint(s, &k);
413 if (ih < 0)
414 return ih;
415
416 if (!ih) {
417 if (!idle_hint) {
418 if (k.monotonic < ts.monotonic)
419 ts = k;
420 } else {
421 idle_hint = false;
422 ts = k;
423 }
424 } else if (idle_hint) {
425
426 if (k.monotonic > ts.monotonic)
427 ts = k;
428 }
429 }
430
431 if (t)
432 *t = ts;
433
434 return idle_hint;
435 }
436
437 bool manager_shall_kill(Manager *m, const char *user) {
438 assert(m);
439 assert(user);
440
441 if (!m->kill_exclude_users && streq(user, "root"))
442 return false;
443
444 if (strv_contains(m->kill_exclude_users, user))
445 return false;
446
447 if (!strv_isempty(m->kill_only_users))
448 return strv_contains(m->kill_only_users, user);
449
450 return m->kill_user_processes;
451 }
452
453 int config_parse_n_autovts(
454 const char *unit,
455 const char *filename,
456 unsigned line,
457 const char *section,
458 unsigned section_line,
459 const char *lvalue,
460 int ltype,
461 const char *rvalue,
462 void *data,
463 void *userdata) {
464
465 unsigned *n = data;
466 unsigned o;
467 int r;
468
469 assert(filename);
470 assert(lvalue);
471 assert(rvalue);
472 assert(data);
473
474 r = safe_atou(rvalue, &o);
475 if (r < 0) {
476 log_syntax(unit, LOG_WARNING, filename, line, r,
477 "Failed to parse number of autovts, ignoring: %s", rvalue);
478 return 0;
479 }
480
481 if (o > 15) {
482 log_syntax(unit, LOG_WARNING, filename, line, 0,
483 "A maximum of 15 autovts are supported, ignoring: %s", rvalue);
484 return 0;
485 }
486
487 *n = o;
488 return 0;
489 }
490
491 static int vt_is_busy(unsigned vtnr) {
492 struct vt_stat vt_stat;
493 int r;
494 _cleanup_close_ int fd = -1;
495
496 assert(vtnr >= 1);
497
498 /* VT_GETSTATE "cannot return state for more than 16 VTs, since v_state is short" */
499 assert(vtnr <= 15);
500
501 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
502 * we'd open the latter we'd open the foreground tty which
503 * hence would be unconditionally busy. By opening /dev/tty1
504 * we avoid this. Since tty1 is special and needs to be an
505 * explicitly loaded getty or DM this is safe. */
506
507 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
508 if (fd < 0)
509 return -errno;
510
511 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
512 r = -errno;
513 else
514 r = !!(vt_stat.v_state & (1 << vtnr));
515
516 return r;
517 }
518
519 int manager_spawn_autovt(Manager *m, unsigned vtnr) {
520 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
521 char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned)];
522 int r;
523
524 assert(m);
525 assert(vtnr >= 1);
526
527 if (vtnr > m->n_autovts &&
528 vtnr != m->reserve_vt)
529 return 0;
530
531 if (vtnr != m->reserve_vt) {
532 /* If this is the reserved TTY, we'll start the getty
533 * on it in any case, but otherwise only if it is not
534 * busy. */
535
536 r = vt_is_busy(vtnr);
537 if (r < 0)
538 return r;
539 else if (r > 0)
540 return -EBUSY;
541 }
542
543 xsprintf(name, "autovt@tty%u.service", vtnr);
544 r = sd_bus_call_method(
545 m->bus,
546 "org.freedesktop.systemd1",
547 "/org/freedesktop/systemd1",
548 "org.freedesktop.systemd1.Manager",
549 "StartUnit",
550 &error,
551 NULL,
552 "ss", name, "fail");
553 if (r < 0)
554 return log_error_errno(r, "Failed to start %s: %s", name, bus_error_message(&error, r));
555
556 return 0;
557 }
558
559 bool manager_is_lid_closed(Manager *m) {
560 Button *b;
561
562 HASHMAP_FOREACH(b, m->buttons)
563 if (b->lid_closed)
564 return true;
565
566 return false;
567 }
568
569 static bool manager_is_docked(Manager *m) {
570 Button *b;
571
572 HASHMAP_FOREACH(b, m->buttons)
573 if (b->docked)
574 return true;
575
576 return false;
577 }
578
579 static int manager_count_external_displays(Manager *m) {
580 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
581 sd_device *d;
582 int r, n = 0;
583
584 r = sd_device_enumerator_new(&e);
585 if (r < 0)
586 return r;
587
588 r = sd_device_enumerator_allow_uninitialized(e);
589 if (r < 0)
590 return r;
591
592 r = sd_device_enumerator_add_match_subsystem(e, "drm", true);
593 if (r < 0)
594 return r;
595
596 FOREACH_DEVICE(e, d) {
597 const char *status, *enabled, *dash, *nn, *subsys;
598 sd_device *p;
599
600 if (sd_device_get_parent(d, &p) < 0)
601 continue;
602
603 /* If the parent shares the same subsystem as the
604 * device we are looking at then it is a connector,
605 * which is what we are interested in. */
606 if (sd_device_get_subsystem(p, &subsys) < 0 || !streq(subsys, "drm"))
607 continue;
608
609 if (sd_device_get_sysname(d, &nn) < 0)
610 continue;
611
612 /* Ignore internal displays: the type is encoded in the sysfs name, as the second dash
613 * separated item (the first is the card name, the last the connector number). We implement a
614 * deny list of external displays here, rather than an allow list of internal ones, to ensure
615 * we don't block suspends too eagerly. */
616 dash = strchr(nn, '-');
617 if (!dash)
618 continue;
619
620 dash++;
621 if (!STARTSWITH_SET(dash,
622 "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
623 "Composite-", "SVIDEO-", "Component-",
624 "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-"))
625 continue;
626
627 /* Ignore ports that are not enabled */
628 if (sd_device_get_sysattr_value(d, "enabled", &enabled) < 0 || !streq(enabled, "enabled"))
629 continue;
630
631 /* We count any connector which is not explicitly
632 * "disconnected" as connected. */
633 if (sd_device_get_sysattr_value(d, "status", &status) < 0 || !streq(status, "disconnected"))
634 n++;
635 }
636
637 return n;
638 }
639
640 bool manager_is_docked_or_external_displays(Manager *m) {
641 int n;
642
643 /* If we are docked don't react to lid closing */
644 if (manager_is_docked(m)) {
645 log_debug("System is docked.");
646 return true;
647 }
648
649 /* If we have more than one display connected,
650 * assume that we are docked. */
651 n = manager_count_external_displays(m);
652 if (n < 0)
653 log_warning_errno(n, "Display counting failed: %m");
654 else if (n >= 1) {
655 log_debug("External (%i) displays connected.", n);
656 return true;
657 }
658
659 return false;
660 }
661
662 bool manager_is_on_external_power(void) {
663 int r;
664
665 /* For now we only check for AC power, but 'external power' can apply to anything that isn't an internal
666 * battery */
667 r = on_ac_power();
668 if (r < 0)
669 log_warning_errno(r, "Failed to read AC power status: %m");
670
671 return r != 0; /* Treat failure as 'on AC' */
672 }
673
674 bool manager_all_buttons_ignored(Manager *m) {
675 assert(m);
676
677 if (m->handle_power_key != HANDLE_IGNORE)
678 return false;
679 if (m->handle_power_key_long_press != HANDLE_IGNORE)
680 return false;
681 if (m->handle_suspend_key != HANDLE_IGNORE)
682 return false;
683 if (m->handle_suspend_key_long_press != HANDLE_IGNORE)
684 return false;
685 if (m->handle_hibernate_key != HANDLE_IGNORE)
686 return false;
687 if (m->handle_hibernate_key_long_press != HANDLE_IGNORE)
688 return false;
689 if (m->handle_reboot_key != HANDLE_IGNORE)
690 return false;
691 if (m->handle_reboot_key_long_press != HANDLE_IGNORE)
692 return false;
693 if (m->handle_lid_switch != HANDLE_IGNORE)
694 return false;
695 if (!IN_SET(m->handle_lid_switch_ep, _HANDLE_ACTION_INVALID, HANDLE_IGNORE))
696 return false;
697 if (m->handle_lid_switch_docked != HANDLE_IGNORE)
698 return false;
699
700 return true;
701 }
702
703 int manager_read_utmp(Manager *m) {
704 #if ENABLE_UTMP
705 int r;
706 _cleanup_(utxent_cleanup) bool utmpx = false;
707
708 assert(m);
709
710 if (utmpxname(_PATH_UTMPX) < 0)
711 return log_error_errno(errno, "Failed to set utmp path to " _PATH_UTMPX ": %m");
712
713 utmpx = utxent_start();
714
715 for (;;) {
716 _cleanup_free_ char *t = NULL;
717 struct utmpx *u;
718 const char *c;
719 Session *s;
720
721 errno = 0;
722 u = getutxent();
723 if (!u) {
724 if (errno != 0)
725 log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m");
726 return 0;
727 }
728
729 if (u->ut_type != USER_PROCESS)
730 continue;
731
732 if (!pid_is_valid(u->ut_pid))
733 continue;
734
735 t = strndup(u->ut_line, sizeof(u->ut_line));
736 if (!t)
737 return log_oom();
738
739 c = path_startswith(t, "/dev/");
740 if (c) {
741 r = free_and_strdup(&t, c);
742 if (r < 0)
743 return log_oom();
744 }
745
746 if (isempty(t))
747 continue;
748
749 s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(u->ut_pid));
750 if (!s)
751 continue;
752
753 if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) {
754 /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In
755 * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY
756 * information and never acquire it again. */
757
758 s->tty = mfree(s->tty);
759 s->tty_validity = TTY_UTMP_INCONSISTENT;
760 log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id);
761 continue;
762 }
763
764 /* Never override what we figured out once */
765 if (s->tty || s->tty_validity >= 0)
766 continue;
767
768 s->tty = TAKE_PTR(t);
769 s->tty_validity = TTY_FROM_UTMP;
770 log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
771 }
772
773 #else
774 return 0;
775 #endif
776 }
777
778 #if ENABLE_UTMP
779 static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) {
780 Manager *m = userdata;
781
782 assert(m);
783
784 /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's
785 * reestablish the watch on whatever there's now. */
786 if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0)
787 manager_connect_utmp(m);
788
789 (void) manager_read_utmp(m);
790 return 0;
791 }
792 #endif
793
794 void manager_connect_utmp(Manager *m) {
795 #if ENABLE_UTMP
796 sd_event_source *s = NULL;
797 int r;
798
799 assert(m);
800
801 /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM
802 * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known
803 * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and
804 * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry.
805 *
806 * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle
807 * detection (which, for tty sessions, relies on the TTY used) */
808
809 r = sd_event_add_inotify(m->event, &s, _PATH_UTMPX, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m);
810 if (r < 0)
811 log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " _PATH_UTMPX ", ignoring: %m");
812 else {
813 r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
814 if (r < 0)
815 log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m");
816
817 (void) sd_event_source_set_description(s, "utmp");
818 }
819
820 sd_event_source_unref(m->utmp_event_source);
821 m->utmp_event_source = s;
822 #endif
823 }
824
825 void manager_reconnect_utmp(Manager *m) {
826 #if ENABLE_UTMP
827 assert(m);
828
829 if (m->utmp_event_source)
830 return;
831
832 manager_connect_utmp(m);
833 #endif
834 }
835
836 int manager_read_efi_boot_loader_entries(Manager *m) {
837 #if ENABLE_EFI
838 int r;
839
840 assert(m);
841 if (m->efi_boot_loader_entries_set)
842 return 0;
843
844 r = efi_loader_get_entries(&m->efi_boot_loader_entries);
845 if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r)) {
846 log_debug_errno(r, "Boot loader reported no entries.");
847 m->efi_boot_loader_entries_set = true;
848 return 0;
849 }
850 if (r < 0)
851 return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
852
853 m->efi_boot_loader_entries_set = true;
854 return 1;
855 #else
856 return 0;
857 #endif
858 }