]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-core.c
Merge pull request #8086 from hdante/sdboot-setmode-v2
[thirdparty/systemd.git] / src / login / logind-core.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2011 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <fcntl.h>
22 #include <pwd.h>
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
25 #include <linux/vt.h>
26
27 #include "alloc-util.h"
28 #include "bus-error.h"
29 #include "bus-util.h"
30 #include "cgroup-util.h"
31 #include "fd-util.h"
32 #include "logind.h"
33 #include "parse-util.h"
34 #include "process-util.h"
35 #include "strv.h"
36 #include "terminal-util.h"
37 #include "udev-util.h"
38 #include "user-util.h"
39
40 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
41 Device *d;
42
43 assert(m);
44 assert(sysfs);
45
46 d = hashmap_get(m->devices, sysfs);
47 if (d)
48 /* we support adding master-flags, but not removing them */
49 d->master = d->master || master;
50 else {
51 d = device_new(m, sysfs, master);
52 if (!d)
53 return -ENOMEM;
54 }
55
56 if (_device)
57 *_device = d;
58
59 return 0;
60 }
61
62 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
63 Seat *s;
64
65 assert(m);
66 assert(id);
67
68 s = hashmap_get(m->seats, id);
69 if (!s) {
70 s = seat_new(m, id);
71 if (!s)
72 return -ENOMEM;
73 }
74
75 if (_seat)
76 *_seat = s;
77
78 return 0;
79 }
80
81 int manager_add_session(Manager *m, const char *id, Session **_session) {
82 Session *s;
83
84 assert(m);
85 assert(id);
86
87 s = hashmap_get(m->sessions, id);
88 if (!s) {
89 s = session_new(m, id);
90 if (!s)
91 return -ENOMEM;
92 }
93
94 if (_session)
95 *_session = s;
96
97 return 0;
98 }
99
100 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
101 User *u;
102 int r;
103
104 assert(m);
105 assert(name);
106
107 u = hashmap_get(m->users, UID_TO_PTR(uid));
108 if (!u) {
109 r = user_new(&u, m, uid, gid, name);
110 if (r < 0)
111 return r;
112 }
113
114 if (_user)
115 *_user = u;
116
117 return 0;
118 }
119
120 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
121 uid_t uid;
122 gid_t gid;
123 int r;
124
125 assert(m);
126 assert(name);
127
128 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
129 if (r < 0)
130 return r;
131
132 return manager_add_user(m, uid, gid, name, _user);
133 }
134
135 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
136 struct passwd *p;
137
138 assert(m);
139
140 errno = 0;
141 p = getpwuid(uid);
142 if (!p)
143 return errno > 0 ? -errno : -ENOENT;
144
145 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
146 }
147
148 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
149 Inhibitor *i;
150
151 assert(m);
152 assert(id);
153
154 i = hashmap_get(m->inhibitors, id);
155 if (i) {
156 if (_inhibitor)
157 *_inhibitor = i;
158
159 return 0;
160 }
161
162 i = inhibitor_new(m, id);
163 if (!i)
164 return -ENOMEM;
165
166 if (_inhibitor)
167 *_inhibitor = i;
168
169 return 0;
170 }
171
172 int manager_add_button(Manager *m, const char *name, Button **_button) {
173 Button *b;
174
175 assert(m);
176 assert(name);
177
178 b = hashmap_get(m->buttons, name);
179 if (!b) {
180 b = button_new(m, name);
181 if (!b)
182 return -ENOMEM;
183 }
184
185 if (_button)
186 *_button = b;
187
188 return 0;
189 }
190
191 int manager_process_seat_device(Manager *m, struct udev_device *d) {
192 Device *device;
193 int r;
194
195 assert(m);
196
197 if (streq_ptr(udev_device_get_action(d), "remove")) {
198
199 device = hashmap_get(m->devices, udev_device_get_syspath(d));
200 if (!device)
201 return 0;
202
203 seat_add_to_gc_queue(device->seat);
204 device_free(device);
205
206 } else {
207 const char *sn;
208 Seat *seat = NULL;
209 bool master;
210
211 sn = udev_device_get_property_value(d, "ID_SEAT");
212 if (isempty(sn))
213 sn = "seat0";
214
215 if (!seat_name_is_valid(sn)) {
216 log_warning("Device with invalid seat name %s found, ignoring.", sn);
217 return 0;
218 }
219
220 seat = hashmap_get(m->seats, sn);
221 master = udev_device_has_tag(d, "master-of-seat");
222
223 /* Ignore non-master devices for unknown seats */
224 if (!master && !seat)
225 return 0;
226
227 r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
228 if (r < 0)
229 return r;
230
231 if (!seat) {
232 r = manager_add_seat(m, sn, &seat);
233 if (r < 0) {
234 if (!device->seat)
235 device_free(device);
236
237 return r;
238 }
239 }
240
241 device_attach(device, seat);
242 seat_start(seat);
243 }
244
245 return 0;
246 }
247
248 int manager_process_button_device(Manager *m, struct udev_device *d) {
249 Button *b;
250
251 int r;
252
253 assert(m);
254
255 if (streq_ptr(udev_device_get_action(d), "remove")) {
256
257 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
258 if (!b)
259 return 0;
260
261 button_free(b);
262
263 } else {
264 const char *sn;
265
266 r = manager_add_button(m, udev_device_get_sysname(d), &b);
267 if (r < 0)
268 return r;
269
270 sn = udev_device_get_property_value(d, "ID_SEAT");
271 if (isempty(sn))
272 sn = "seat0";
273
274 button_set_seat(b, sn);
275
276 r = button_open(b);
277 if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error
278 * opening the device?) let's close the button again. */
279 button_free(b);
280 }
281
282 return 0;
283 }
284
285 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
286 _cleanup_free_ char *unit = NULL;
287 Session *s;
288 int r;
289
290 assert(m);
291
292 if (!pid_is_valid(pid))
293 return -EINVAL;
294
295 r = cg_pid_get_unit(pid, &unit);
296 if (r < 0)
297 return 0;
298
299 s = hashmap_get(m->session_units, unit);
300 if (!s)
301 return 0;
302
303 if (session)
304 *session = s;
305 return 1;
306 }
307
308 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
309 _cleanup_free_ char *unit = NULL;
310 User *u;
311 int r;
312
313 assert(m);
314 assert(user);
315
316 if (!pid_is_valid(pid))
317 return -EINVAL;
318
319 r = cg_pid_get_slice(pid, &unit);
320 if (r < 0)
321 return 0;
322
323 u = hashmap_get(m->user_units, unit);
324 if (!u)
325 return 0;
326
327 *user = u;
328 return 1;
329 }
330
331 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
332 Session *s;
333 bool idle_hint;
334 dual_timestamp ts = DUAL_TIMESTAMP_NULL;
335 Iterator i;
336
337 assert(m);
338
339 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
340
341 HASHMAP_FOREACH(s, m->sessions, i) {
342 dual_timestamp k;
343 int ih;
344
345 ih = session_get_idle_hint(s, &k);
346 if (ih < 0)
347 return ih;
348
349 if (!ih) {
350 if (!idle_hint) {
351 if (k.monotonic < ts.monotonic)
352 ts = k;
353 } else {
354 idle_hint = false;
355 ts = k;
356 }
357 } else if (idle_hint) {
358
359 if (k.monotonic > ts.monotonic)
360 ts = k;
361 }
362 }
363
364 if (t)
365 *t = ts;
366
367 return idle_hint;
368 }
369
370 bool manager_shall_kill(Manager *m, const char *user) {
371 assert(m);
372 assert(user);
373
374 if (!m->kill_exclude_users && streq(user, "root"))
375 return false;
376
377 if (strv_contains(m->kill_exclude_users, user))
378 return false;
379
380 if (!strv_isempty(m->kill_only_users))
381 return strv_contains(m->kill_only_users, user);
382
383 return m->kill_user_processes;
384 }
385
386 int config_parse_n_autovts(
387 const char *unit,
388 const char *filename,
389 unsigned line,
390 const char *section,
391 unsigned section_line,
392 const char *lvalue,
393 int ltype,
394 const char *rvalue,
395 void *data,
396 void *userdata) {
397
398 unsigned *n = data;
399 unsigned o;
400 int r;
401
402 assert(filename);
403 assert(lvalue);
404 assert(rvalue);
405 assert(data);
406
407 r = safe_atou(rvalue, &o);
408 if (r < 0) {
409 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse number of autovts, ignoring: %s", rvalue);
410 return 0;
411 }
412
413 if (o > 15) {
414 log_syntax(unit, LOG_ERR, filename, line, r, "A maximum of 15 autovts are supported, ignoring: %s", rvalue);
415 return 0;
416 }
417
418 *n = o;
419 return 0;
420 }
421
422 static int vt_is_busy(unsigned int vtnr) {
423 struct vt_stat vt_stat;
424 int r = 0;
425 _cleanup_close_ int fd;
426
427 assert(vtnr >= 1);
428
429 /* VT_GETSTATE "cannot return state for more than 16 VTs, since v_state is short" */
430 assert(vtnr <= 15);
431
432 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
433 * we'd open the latter we'd open the foreground tty which
434 * hence would be unconditionally busy. By opening /dev/tty1
435 * we avoid this. Since tty1 is special and needs to be an
436 * explicitly loaded getty or DM this is safe. */
437
438 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
439 if (fd < 0)
440 return -errno;
441
442 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
443 r = -errno;
444 else
445 r = !!(vt_stat.v_state & (1 << vtnr));
446
447 return r;
448 }
449
450 int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
451 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
452 char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned int)];
453 int r;
454
455 assert(m);
456 assert(vtnr >= 1);
457
458 if (vtnr > m->n_autovts &&
459 vtnr != m->reserve_vt)
460 return 0;
461
462 if (vtnr != m->reserve_vt) {
463 /* If this is the reserved TTY, we'll start the getty
464 * on it in any case, but otherwise only if it is not
465 * busy. */
466
467 r = vt_is_busy(vtnr);
468 if (r < 0)
469 return r;
470 else if (r > 0)
471 return -EBUSY;
472 }
473
474 snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
475 r = sd_bus_call_method(
476 m->bus,
477 "org.freedesktop.systemd1",
478 "/org/freedesktop/systemd1",
479 "org.freedesktop.systemd1.Manager",
480 "StartUnit",
481 &error,
482 NULL,
483 "ss", name, "fail");
484 if (r < 0)
485 log_error("Failed to start %s: %s", name, bus_error_message(&error, r));
486
487 return r;
488 }
489
490 static bool manager_is_docked(Manager *m) {
491 Iterator i;
492 Button *b;
493
494 HASHMAP_FOREACH(b, m->buttons, i)
495 if (b->docked)
496 return true;
497
498 return false;
499 }
500
501 static int manager_count_external_displays(Manager *m) {
502 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
503 struct udev_list_entry *item = NULL, *first = NULL;
504 int r;
505 int n = 0;
506
507 e = udev_enumerate_new(m->udev);
508 if (!e)
509 return -ENOMEM;
510
511 r = udev_enumerate_add_match_subsystem(e, "drm");
512 if (r < 0)
513 return r;
514
515 r = udev_enumerate_scan_devices(e);
516 if (r < 0)
517 return r;
518
519 first = udev_enumerate_get_list_entry(e);
520 udev_list_entry_foreach(item, first) {
521 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
522 struct udev_device *p;
523 const char *status, *enabled, *dash, *nn, *i;
524 bool external = false;
525
526 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
527 if (!d)
528 return -ENOMEM;
529
530 p = udev_device_get_parent(d);
531 if (!p)
532 continue;
533
534 /* If the parent shares the same subsystem as the
535 * device we are looking at then it is a connector,
536 * which is what we are interested in. */
537 if (!streq_ptr(udev_device_get_subsystem(p), "drm"))
538 continue;
539
540 nn = udev_device_get_sysname(d);
541 if (!nn)
542 continue;
543
544 /* Ignore internal displays: the type is encoded in
545 * the sysfs name, as the second dash separated item
546 * (the first is the card name, the last the connector
547 * number). We implement a whitelist of external
548 * displays here, rather than a whitelist, to ensure
549 * we don't block suspends too eagerly. */
550 dash = strchr(nn, '-');
551 if (!dash)
552 continue;
553
554 dash++;
555 FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
556 "Composite-", "SVIDEO-", "Component-",
557 "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") {
558
559 if (startswith(dash, i)) {
560 external = true;
561 break;
562 }
563 }
564 if (!external)
565 continue;
566
567 /* Ignore ports that are not enabled */
568 enabled = udev_device_get_sysattr_value(d, "enabled");
569 if (!enabled)
570 continue;
571 if (!streq_ptr(enabled, "enabled"))
572 continue;
573
574 /* We count any connector which is not explicitly
575 * "disconnected" as connected. */
576 status = udev_device_get_sysattr_value(d, "status");
577 if (!streq_ptr(status, "disconnected"))
578 n++;
579 }
580
581 return n;
582 }
583
584 bool manager_is_docked_or_external_displays(Manager *m) {
585 int n;
586
587 /* If we are docked don't react to lid closing */
588 if (manager_is_docked(m)) {
589 log_debug("System is docked.");
590 return true;
591 }
592
593 /* If we have more than one display connected,
594 * assume that we are docked. */
595 n = manager_count_external_displays(m);
596 if (n < 0)
597 log_warning_errno(n, "Display counting failed: %m");
598 else if (n >= 1) {
599 log_debug("External (%i) displays connected.", n);
600 return true;
601 }
602
603 return false;
604 }
605
606 bool manager_is_on_external_power(void) {
607 int r;
608
609 /* For now we only check for AC power, but 'external power' can apply
610 * to anything that isn't an internal battery */
611 r = on_ac_power();
612 if (r < 0)
613 log_warning_errno(r, "Failed to read AC power status: %m");
614 else if (r > 0)
615 return true;
616
617 return false;
618 }
619
620 bool manager_all_buttons_ignored(Manager *m) {
621 assert(m);
622
623 if (m->handle_power_key != HANDLE_IGNORE)
624 return false;
625 if (m->handle_suspend_key != HANDLE_IGNORE)
626 return false;
627 if (m->handle_hibernate_key != HANDLE_IGNORE)
628 return false;
629 if (m->handle_lid_switch != HANDLE_IGNORE)
630 return false;
631 if (m->handle_lid_switch_ep != _HANDLE_ACTION_INVALID &&
632 m->handle_lid_switch_ep != HANDLE_IGNORE)
633 return false;
634 if (m->handle_lid_switch_docked != HANDLE_IGNORE)
635 return false;
636
637 return true;
638 }