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 
manager_reset_config(Manager * m)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 
manager_parse_config_file(Manager * m)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 
manager_add_device(Manager * m,const char * sysfs,bool master,Device ** ret_device)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 
manager_add_seat(Manager * m,const char * id,Seat ** ret_seat)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 
manager_add_session(Manager * m,const char * id,Session ** ret_session)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 
manager_add_user(Manager * m,UserRecord * ur,User ** ret_user)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 
manager_add_user_by_name(Manager * m,const char * name,User ** ret_user)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 
manager_add_user_by_uid(Manager * m,uid_t uid,User ** ret_user)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 
manager_add_inhibitor(Manager * m,const char * id,Inhibitor ** ret)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 
manager_add_button(Manager * m,const char * name,Button ** ret_button)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 
manager_process_seat_device(Manager * m,sd_device * d)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 
manager_process_button_device(Manager * m,sd_device * d)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 
manager_get_session_by_pid(Manager * m,pid_t pid,Session ** ret)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 
manager_get_user_by_pid(Manager * m,pid_t pid,User ** ret)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 
manager_get_idle_hint(Manager * m,dual_timestamp * t)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 
manager_shall_kill(Manager * m,const char * user)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 
config_parse_n_autovts(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)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 
vt_is_busy(unsigned vtnr)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 
manager_spawn_autovt(Manager * m,unsigned vtnr)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 
manager_is_lid_closed(Manager * m)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 
manager_is_docked(Manager * m)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 
manager_count_external_displays(Manager * m)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 
manager_is_docked_or_external_displays(Manager * m)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 
manager_is_on_external_power(void)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 
manager_all_buttons_ignored(Manager * m)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 
manager_read_utmp(Manager * m)703 int manager_read_utmp(Manager *m) {
704 #if ENABLE_UTMP
705         int r;
706         _unused_ _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 == ENOENT)
725                                 log_debug_errno(errno, _PATH_UTMPX " does not exist, ignoring.");
726                         else if (errno != 0)
727                                 log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m");
728                         return 0;
729                 }
730 
731                 if (u->ut_type != USER_PROCESS)
732                         continue;
733 
734                 if (!pid_is_valid(u->ut_pid))
735                         continue;
736 
737                 t = strndup(u->ut_line, sizeof(u->ut_line));
738                 if (!t)
739                         return log_oom();
740 
741                 c = path_startswith(t, "/dev/");
742                 if (c) {
743                         r = free_and_strdup(&t, c);
744                         if (r < 0)
745                                 return log_oom();
746                 }
747 
748                 if (isempty(t))
749                         continue;
750 
751                 s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(u->ut_pid));
752                 if (!s)
753                         continue;
754 
755                 if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) {
756                         /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In
757                          * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY
758                          * information and never acquire it again. */
759 
760                         s->tty = mfree(s->tty);
761                         s->tty_validity = TTY_UTMP_INCONSISTENT;
762                         log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id);
763                         continue;
764                 }
765 
766                 /* Never override what we figured out once */
767                 if (s->tty || s->tty_validity >= 0)
768                         continue;
769 
770                 s->tty = TAKE_PTR(t);
771                 s->tty_validity = TTY_FROM_UTMP;
772                 log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
773         }
774 
775 #else
776         return 0;
777 #endif
778 }
779 
780 #if ENABLE_UTMP
manager_dispatch_utmp(sd_event_source * s,const struct inotify_event * event,void * userdata)781 static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) {
782         Manager *m = userdata;
783 
784         assert(m);
785 
786         /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's
787          * reestablish the watch on whatever there's now. */
788         if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0)
789                 manager_connect_utmp(m);
790 
791         (void) manager_read_utmp(m);
792         return 0;
793 }
794 #endif
795 
manager_connect_utmp(Manager * m)796 void manager_connect_utmp(Manager *m) {
797 #if ENABLE_UTMP
798         sd_event_source *s = NULL;
799         int r;
800 
801         assert(m);
802 
803         /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM
804          * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known
805          * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and
806          * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry.
807          *
808          * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle
809          * detection (which, for tty sessions, relies on the TTY used) */
810 
811         r = sd_event_add_inotify(m->event, &s, _PATH_UTMPX, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m);
812         if (r < 0)
813                 log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " _PATH_UTMPX ", ignoring: %m");
814         else {
815                 r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE);
816                 if (r < 0)
817                         log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m");
818 
819                 (void) sd_event_source_set_description(s, "utmp");
820         }
821 
822         sd_event_source_unref(m->utmp_event_source);
823         m->utmp_event_source = s;
824 #endif
825 }
826 
manager_reconnect_utmp(Manager * m)827 void manager_reconnect_utmp(Manager *m) {
828 #if ENABLE_UTMP
829         assert(m);
830 
831         if (m->utmp_event_source)
832                 return;
833 
834         manager_connect_utmp(m);
835 #endif
836 }
837 
manager_read_efi_boot_loader_entries(Manager * m)838 int manager_read_efi_boot_loader_entries(Manager *m) {
839 #if ENABLE_EFI
840         int r;
841 
842         assert(m);
843         if (m->efi_boot_loader_entries_set)
844                 return 0;
845 
846         r = efi_loader_get_entries(&m->efi_boot_loader_entries);
847         if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r)) {
848                 log_debug_errno(r, "Boot loader reported no entries.");
849                 m->efi_boot_loader_entries_set = true;
850                 return 0;
851         }
852         if (r < 0)
853                 return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
854 
855         m->efi_boot_loader_entries_set = true;
856         return 1;
857 #else
858         return 0;
859 #endif
860 }
861