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