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