]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind.c
login: make hold-off timeout configurable
[thirdparty/systemd.git] / src / login / logind.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <libudev.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "sd-daemon.h"
29 #include "strv.h"
30 #include "conf-parser.h"
31 #include "bus-util.h"
32 #include "bus-error.h"
33 #include "logind.h"
34 #include "udev-util.h"
35
36 Manager *manager_new(void) {
37 Manager *m;
38 int r;
39
40 m = new0(Manager, 1);
41 if (!m)
42 return NULL;
43
44 m->console_active_fd = -1;
45 m->reserve_vt_fd = -1;
46
47 m->n_autovts = 6;
48 m->reserve_vt = 6;
49 m->remove_ipc = true;
50 m->inhibit_delay_max = 5 * USEC_PER_SEC;
51 m->handle_power_key = HANDLE_POWEROFF;
52 m->handle_suspend_key = HANDLE_SUSPEND;
53 m->handle_hibernate_key = HANDLE_HIBERNATE;
54 m->handle_lid_switch = HANDLE_SUSPEND;
55 m->handle_lid_switch_docked = HANDLE_IGNORE;
56 m->lid_switch_ignore_inhibited = true;
57 m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
58
59 m->idle_action_usec = 30 * USEC_PER_MINUTE;
60 m->idle_action = HANDLE_IGNORE;
61 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
62
63 m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
64
65 m->devices = hashmap_new(&string_hash_ops);
66 m->seats = hashmap_new(&string_hash_ops);
67 m->sessions = hashmap_new(&string_hash_ops);
68 m->users = hashmap_new(NULL);
69 m->inhibitors = hashmap_new(&string_hash_ops);
70 m->buttons = hashmap_new(&string_hash_ops);
71
72 m->user_units = hashmap_new(&string_hash_ops);
73 m->session_units = hashmap_new(&string_hash_ops);
74
75 m->busnames = set_new(&string_hash_ops);
76
77 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
78 !m->user_units || !m->session_units)
79 goto fail;
80
81 m->kill_exclude_users = strv_new("root", NULL);
82 if (!m->kill_exclude_users)
83 goto fail;
84
85 m->udev = udev_new();
86 if (!m->udev)
87 goto fail;
88
89 r = sd_event_default(&m->event);
90 if (r < 0)
91 goto fail;
92
93 sd_event_set_watchdog(m->event, true);
94
95 return m;
96
97 fail:
98 manager_free(m);
99 return NULL;
100 }
101
102 void manager_free(Manager *m) {
103 Session *session;
104 User *u;
105 Device *d;
106 Seat *s;
107 Inhibitor *i;
108 Button *b;
109
110 assert(m);
111
112 while ((session = hashmap_first(m->sessions)))
113 session_free(session);
114
115 while ((u = hashmap_first(m->users)))
116 user_free(u);
117
118 while ((d = hashmap_first(m->devices)))
119 device_free(d);
120
121 while ((s = hashmap_first(m->seats)))
122 seat_free(s);
123
124 while ((i = hashmap_first(m->inhibitors)))
125 inhibitor_free(i);
126
127 while ((b = hashmap_first(m->buttons)))
128 button_free(b);
129
130 hashmap_free(m->devices);
131 hashmap_free(m->seats);
132 hashmap_free(m->sessions);
133 hashmap_free(m->users);
134 hashmap_free(m->inhibitors);
135 hashmap_free(m->buttons);
136
137 hashmap_free(m->user_units);
138 hashmap_free(m->session_units);
139
140 set_free_free(m->busnames);
141
142 sd_event_source_unref(m->idle_action_event_source);
143
144 sd_event_source_unref(m->console_active_event_source);
145 sd_event_source_unref(m->udev_seat_event_source);
146 sd_event_source_unref(m->udev_device_event_source);
147 sd_event_source_unref(m->udev_vcsa_event_source);
148 sd_event_source_unref(m->udev_button_event_source);
149 sd_event_source_unref(m->lid_switch_ignore_event_source);
150
151 safe_close(m->console_active_fd);
152
153 if (m->udev_seat_monitor)
154 udev_monitor_unref(m->udev_seat_monitor);
155 if (m->udev_device_monitor)
156 udev_monitor_unref(m->udev_device_monitor);
157 if (m->udev_vcsa_monitor)
158 udev_monitor_unref(m->udev_vcsa_monitor);
159 if (m->udev_button_monitor)
160 udev_monitor_unref(m->udev_button_monitor);
161
162 if (m->udev)
163 udev_unref(m->udev);
164
165 bus_verify_polkit_async_registry_free(m->polkit_registry);
166
167 sd_bus_unref(m->bus);
168 sd_event_unref(m->event);
169
170 safe_close(m->reserve_vt_fd);
171
172 strv_free(m->kill_only_users);
173 strv_free(m->kill_exclude_users);
174
175 free(m->action_job);
176 free(m);
177 }
178
179 static int manager_enumerate_devices(Manager *m) {
180 struct udev_list_entry *item = NULL, *first = NULL;
181 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
182 int r;
183
184 assert(m);
185
186 /* Loads devices from udev and creates seats for them as
187 * necessary */
188
189 e = udev_enumerate_new(m->udev);
190 if (!e)
191 return -ENOMEM;
192
193 r = udev_enumerate_add_match_tag(e, "master-of-seat");
194 if (r < 0)
195 return r;
196
197 r = udev_enumerate_add_match_is_initialized(e);
198 if (r < 0)
199 return r;
200
201 r = udev_enumerate_scan_devices(e);
202 if (r < 0)
203 return r;
204
205 first = udev_enumerate_get_list_entry(e);
206 udev_list_entry_foreach(item, first) {
207 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
208 int k;
209
210 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
211 if (!d)
212 return -ENOMEM;
213
214 k = manager_process_seat_device(m, d);
215 if (k < 0)
216 r = k;
217 }
218
219 return r;
220 }
221
222 static int manager_enumerate_buttons(Manager *m) {
223 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
224 struct udev_list_entry *item = NULL, *first = NULL;
225 int r;
226
227 assert(m);
228
229 /* Loads buttons from udev */
230
231 if (m->handle_power_key == HANDLE_IGNORE &&
232 m->handle_suspend_key == HANDLE_IGNORE &&
233 m->handle_hibernate_key == HANDLE_IGNORE &&
234 m->handle_lid_switch == HANDLE_IGNORE &&
235 m->handle_lid_switch_docked == HANDLE_IGNORE)
236 return 0;
237
238 e = udev_enumerate_new(m->udev);
239 if (!e)
240 return -ENOMEM;
241
242 r = udev_enumerate_add_match_subsystem(e, "input");
243 if (r < 0)
244 return r;
245
246 r = udev_enumerate_add_match_tag(e, "power-switch");
247 if (r < 0)
248 return r;
249
250 r = udev_enumerate_add_match_is_initialized(e);
251 if (r < 0)
252 return r;
253
254 r = udev_enumerate_scan_devices(e);
255 if (r < 0)
256 return r;
257
258 first = udev_enumerate_get_list_entry(e);
259 udev_list_entry_foreach(item, first) {
260 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
261 int k;
262
263 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
264 if (!d)
265 return -ENOMEM;
266
267 k = manager_process_button_device(m, d);
268 if (k < 0)
269 r = k;
270 }
271
272 return r;
273 }
274
275 static int manager_enumerate_seats(Manager *m) {
276 _cleanup_closedir_ DIR *d = NULL;
277 struct dirent *de;
278 int r = 0;
279
280 assert(m);
281
282 /* This loads data about seats stored on disk, but does not
283 * actually create any seats. Removes data of seats that no
284 * longer exist. */
285
286 d = opendir("/run/systemd/seats");
287 if (!d) {
288 if (errno == ENOENT)
289 return 0;
290
291 log_error_errno(errno, "Failed to open /run/systemd/seats: %m");
292 return -errno;
293 }
294
295 FOREACH_DIRENT(de, d, return -errno) {
296 Seat *s;
297 int k;
298
299 if (!dirent_is_file(de))
300 continue;
301
302 s = hashmap_get(m->seats, de->d_name);
303 if (!s) {
304 unlinkat(dirfd(d), de->d_name, 0);
305 continue;
306 }
307
308 k = seat_load(s);
309 if (k < 0)
310 r = k;
311 }
312
313 return r;
314 }
315
316 static int manager_enumerate_linger_users(Manager *m) {
317 _cleanup_closedir_ DIR *d = NULL;
318 struct dirent *de;
319 int r = 0;
320
321 assert(m);
322
323 d = opendir("/var/lib/systemd/linger");
324 if (!d) {
325 if (errno == ENOENT)
326 return 0;
327
328 log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m");
329 return -errno;
330 }
331
332 FOREACH_DIRENT(de, d, return -errno) {
333 int k;
334
335 if (!dirent_is_file(de))
336 continue;
337
338 k = manager_add_user_by_name(m, de->d_name, NULL);
339 if (k < 0) {
340 log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
341 r = k;
342 }
343 }
344
345 return r;
346 }
347
348 static int manager_enumerate_users(Manager *m) {
349 _cleanup_closedir_ DIR *d = NULL;
350 struct dirent *de;
351 int r, k;
352
353 assert(m);
354
355 /* Add lingering users */
356 r = manager_enumerate_linger_users(m);
357
358 /* Read in user data stored on disk */
359 d = opendir("/run/systemd/users");
360 if (!d) {
361 if (errno == ENOENT)
362 return 0;
363
364 log_error_errno(errno, "Failed to open /run/systemd/users: %m");
365 return -errno;
366 }
367
368 FOREACH_DIRENT(de, d, return -errno) {
369 User *u;
370
371 if (!dirent_is_file(de))
372 continue;
373
374 k = manager_add_user_by_name(m, de->d_name, &u);
375 if (k < 0) {
376 log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
377
378 r = k;
379 continue;
380 }
381
382 user_add_to_gc_queue(u);
383
384 k = user_load(u);
385 if (k < 0)
386 r = k;
387 }
388
389 return r;
390 }
391
392 static int manager_enumerate_sessions(Manager *m) {
393 _cleanup_closedir_ DIR *d = NULL;
394 struct dirent *de;
395 int r = 0;
396
397 assert(m);
398
399 /* Read in session data stored on disk */
400 d = opendir("/run/systemd/sessions");
401 if (!d) {
402 if (errno == ENOENT)
403 return 0;
404
405 log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
406 return -errno;
407 }
408
409 FOREACH_DIRENT(de, d, return -errno) {
410 struct Session *s;
411 int k;
412
413 if (!dirent_is_file(de))
414 continue;
415
416 if (!session_id_valid(de->d_name)) {
417 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
418 r = -EINVAL;
419 continue;
420 }
421
422 k = manager_add_session(m, de->d_name, &s);
423 if (k < 0) {
424 log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
425
426 r = k;
427 continue;
428 }
429
430 session_add_to_gc_queue(s);
431
432 k = session_load(s);
433 if (k < 0)
434 r = k;
435 }
436
437 return r;
438 }
439
440 static int manager_enumerate_inhibitors(Manager *m) {
441 _cleanup_closedir_ DIR *d = NULL;
442 struct dirent *de;
443 int r = 0;
444
445 assert(m);
446
447 d = opendir("/run/systemd/inhibit");
448 if (!d) {
449 if (errno == ENOENT)
450 return 0;
451
452 log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
453 return -errno;
454 }
455
456 FOREACH_DIRENT(de, d, return -errno) {
457 int k;
458 Inhibitor *i;
459
460 if (!dirent_is_file(de))
461 continue;
462
463 k = manager_add_inhibitor(m, de->d_name, &i);
464 if (k < 0) {
465 log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
466 r = k;
467 continue;
468 }
469
470 k = inhibitor_load(i);
471 if (k < 0)
472 r = k;
473 }
474
475 return r;
476 }
477
478 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
479 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
480 Manager *m = userdata;
481
482 assert(m);
483
484 d = udev_monitor_receive_device(m->udev_seat_monitor);
485 if (!d)
486 return -ENOMEM;
487
488 manager_process_seat_device(m, d);
489 return 0;
490 }
491
492 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
493 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
494 Manager *m = userdata;
495
496 assert(m);
497
498 d = udev_monitor_receive_device(m->udev_device_monitor);
499 if (!d)
500 return -ENOMEM;
501
502 manager_process_seat_device(m, d);
503 return 0;
504 }
505
506 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
507 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
508 Manager *m = userdata;
509 const char *name;
510
511 assert(m);
512
513 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
514 if (!d)
515 return -ENOMEM;
516
517 name = udev_device_get_sysname(d);
518
519 /* Whenever a VCSA device is removed try to reallocate our
520 * VTs, to make sure our auto VTs never go away. */
521
522 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
523 seat_preallocate_vts(m->seat0);
524
525 return 0;
526 }
527
528 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
529 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
530 Manager *m = userdata;
531
532 assert(m);
533
534 d = udev_monitor_receive_device(m->udev_button_monitor);
535 if (!d)
536 return -ENOMEM;
537
538 manager_process_button_device(m, d);
539 return 0;
540 }
541
542 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
543 Manager *m = userdata;
544
545 assert(m);
546 assert(m->seat0);
547 assert(m->console_active_fd == fd);
548
549 seat_read_active_vt(m->seat0);
550 return 0;
551 }
552
553 static int manager_reserve_vt(Manager *m) {
554 _cleanup_free_ char *p = NULL;
555
556 assert(m);
557
558 if (m->reserve_vt <= 0)
559 return 0;
560
561 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
562 return log_oom();
563
564 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
565 if (m->reserve_vt_fd < 0) {
566
567 /* Don't complain on VT-less systems */
568 if (errno != ENOENT)
569 log_warning_errno(errno, "Failed to pin reserved VT: %m");
570 return -errno;
571 }
572
573 return 0;
574 }
575
576 static int manager_connect_bus(Manager *m) {
577 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
578 int r;
579
580 assert(m);
581 assert(!m->bus);
582
583 r = sd_bus_default_system(&m->bus);
584 if (r < 0)
585 return log_error_errno(r, "Failed to connect to system bus: %m");
586
587 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
588 if (r < 0)
589 return log_error_errno(r, "Failed to add manager object vtable: %m");
590
591 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
592 if (r < 0)
593 return log_error_errno(r, "Failed to add seat object vtable: %m");
594
595 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
596 if (r < 0)
597 return log_error_errno(r, "Failed to add seat enumerator: %m");
598
599 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
600 if (r < 0)
601 return log_error_errno(r, "Failed to add session object vtable: %m");
602
603 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
604 if (r < 0)
605 return log_error_errno(r, "Failed to add session enumerator: %m");
606
607 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
608 if (r < 0)
609 return log_error_errno(r, "Failed to add user object vtable: %m");
610
611 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
612 if (r < 0)
613 return log_error_errno(r, "Failed to add user enumerator: %m");
614
615 r = sd_bus_add_match(m->bus,
616 NULL,
617 "type='signal',"
618 "sender='org.freedesktop.DBus',"
619 "interface='org.freedesktop.DBus',"
620 "member='NameOwnerChanged',"
621 "path='/org/freedesktop/DBus'",
622 match_name_owner_changed, m);
623 if (r < 0)
624 return log_error_errno(r, "Failed to add match for NameOwnerChanged: %m");
625
626 r = sd_bus_add_match(m->bus,
627 NULL,
628 "type='signal',"
629 "sender='org.freedesktop.systemd1',"
630 "interface='org.freedesktop.systemd1.Manager',"
631 "member='JobRemoved',"
632 "path='/org/freedesktop/systemd1'",
633 match_job_removed, m);
634 if (r < 0)
635 return log_error_errno(r, "Failed to add match for JobRemoved: %m");
636
637 r = sd_bus_add_match(m->bus,
638 NULL,
639 "type='signal',"
640 "sender='org.freedesktop.systemd1',"
641 "interface='org.freedesktop.systemd1.Manager',"
642 "member='UnitRemoved',"
643 "path='/org/freedesktop/systemd1'",
644 match_unit_removed, m);
645 if (r < 0)
646 return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
647
648 r = sd_bus_add_match(m->bus,
649 NULL,
650 "type='signal',"
651 "sender='org.freedesktop.systemd1',"
652 "interface='org.freedesktop.DBus.Properties',"
653 "member='PropertiesChanged'",
654 match_properties_changed, m);
655 if (r < 0)
656 return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
657
658 r = sd_bus_add_match(m->bus,
659 NULL,
660 "type='signal',"
661 "sender='org.freedesktop.systemd1',"
662 "interface='org.freedesktop.systemd1.Manager',"
663 "member='Reloading',"
664 "path='/org/freedesktop/systemd1'",
665 match_reloading, m);
666 if (r < 0)
667 return log_error_errno(r, "Failed to add match for Reloading: %m");
668
669 r = sd_bus_call_method(
670 m->bus,
671 "org.freedesktop.systemd1",
672 "/org/freedesktop/systemd1",
673 "org.freedesktop.systemd1.Manager",
674 "Subscribe",
675 &error,
676 NULL, NULL);
677 if (r < 0) {
678 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
679 return r;
680 }
681
682 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
683 if (r < 0)
684 return log_error_errno(r, "Failed to register name: %m");
685
686 r = sd_bus_attach_event(m->bus, m->event, 0);
687 if (r < 0)
688 return log_error_errno(r, "Failed to attach bus to event loop: %m");
689
690 return 0;
691 }
692
693 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
694 Manager *m = data;
695 Session *active, *iter;
696
697 /*
698 * We got a VT-switch signal and we have to acknowledge it immediately.
699 * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
700 * old user-space might run multiple sessions on a single VT, *sigh*.
701 * Therefore, we have to iterate all sessions and find one with a vtfd
702 * on the requested VT.
703 * As only VTs with active controllers have VT_PROCESS set, our current
704 * notion of the active VT might be wrong (for instance if the switch
705 * happens while we setup VT_PROCESS). Therefore, read the current VT
706 * first and then use s->active->vtnr as reference. Note that this is
707 * not racy, as no further VT-switch can happen as long as we're in
708 * synchronous VT_PROCESS mode.
709 */
710
711 assert(m->seat0);
712 seat_read_active_vt(m->seat0);
713
714 active = m->seat0->active;
715 if (!active || active->vtnr < 1) {
716 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
717 return 0;
718 }
719
720 if (active->vtfd >= 0) {
721 session_leave_vt(active);
722 } else {
723 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
724 if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
725 session_leave_vt(iter);
726 break;
727 }
728 }
729 }
730
731 return 0;
732 }
733
734 static int manager_connect_console(Manager *m) {
735 int r;
736
737 assert(m);
738 assert(m->console_active_fd < 0);
739
740 /* On certain architectures (S390 and Xen, and containers),
741 /dev/tty0 does not exist, so don't fail if we can't open
742 it. */
743 if (access("/dev/tty0", F_OK) < 0)
744 return 0;
745
746 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
747 if (m->console_active_fd < 0) {
748
749 /* On some systems the device node /dev/tty0 may exist
750 * even though /sys/class/tty/tty0 does not. */
751 if (errno == ENOENT)
752 return 0;
753
754 log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
755 return -errno;
756 }
757
758 r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
759 if (r < 0) {
760 log_error("Failed to watch foreground console");
761 return r;
762 }
763
764 /*
765 * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
766 * as VT-acquire signal. We ignore any acquire-events (yes, we still
767 * have to provide a valid signal-number for it!) and acknowledge all
768 * release events immediately.
769 */
770
771 if (SIGRTMIN + 1 > SIGRTMAX) {
772 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
773 return -EINVAL;
774 }
775
776 r = ignore_signals(SIGRTMIN + 1, -1);
777 if (r < 0)
778 return log_error_errno(r, "Cannot ignore SIGRTMIN + 1: %m");
779
780 r = sigprocmask_many(SIG_BLOCK, SIGRTMIN, -1);
781 if (r < 0)
782 return log_error_errno(r, "Cannot block SIGRTMIN: %m");
783
784 r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
785 if (r < 0)
786 return r;
787
788 return 0;
789 }
790
791 static int manager_connect_udev(Manager *m) {
792 int r;
793
794 assert(m);
795 assert(!m->udev_seat_monitor);
796 assert(!m->udev_device_monitor);
797 assert(!m->udev_vcsa_monitor);
798 assert(!m->udev_button_monitor);
799
800 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
801 if (!m->udev_seat_monitor)
802 return -ENOMEM;
803
804 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
805 if (r < 0)
806 return r;
807
808 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
809 if (r < 0)
810 return r;
811
812 r = sd_event_add_io(m->event, &m->udev_seat_event_source, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m);
813 if (r < 0)
814 return r;
815
816 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
817 if (!m->udev_device_monitor)
818 return -ENOMEM;
819
820 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
821 if (r < 0)
822 return r;
823
824 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
825 if (r < 0)
826 return r;
827
828 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
829 if (r < 0)
830 return r;
831
832 r = udev_monitor_enable_receiving(m->udev_device_monitor);
833 if (r < 0)
834 return r;
835
836 r = sd_event_add_io(m->event, &m->udev_device_event_source, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m);
837 if (r < 0)
838 return r;
839
840 /* Don't watch keys if nobody cares */
841 if (m->handle_power_key != HANDLE_IGNORE ||
842 m->handle_suspend_key != HANDLE_IGNORE ||
843 m->handle_hibernate_key != HANDLE_IGNORE ||
844 m->handle_lid_switch != HANDLE_IGNORE ||
845 m->handle_lid_switch_docked != HANDLE_IGNORE) {
846
847 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
848 if (!m->udev_button_monitor)
849 return -ENOMEM;
850
851 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
852 if (r < 0)
853 return r;
854
855 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
856 if (r < 0)
857 return r;
858
859 r = udev_monitor_enable_receiving(m->udev_button_monitor);
860 if (r < 0)
861 return r;
862
863 r = sd_event_add_io(m->event, &m->udev_button_event_source, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m);
864 if (r < 0)
865 return r;
866 }
867
868 /* Don't bother watching VCSA devices, if nobody cares */
869 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
870
871 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
872 if (!m->udev_vcsa_monitor)
873 return -ENOMEM;
874
875 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
876 if (r < 0)
877 return r;
878
879 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
880 if (r < 0)
881 return r;
882
883 r = sd_event_add_io(m->event, &m->udev_vcsa_event_source, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m);
884 if (r < 0)
885 return r;
886 }
887
888 return 0;
889 }
890
891 void manager_gc(Manager *m, bool drop_not_started) {
892 Seat *seat;
893 Session *session;
894 User *user;
895
896 assert(m);
897
898 while ((seat = m->seat_gc_queue)) {
899 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
900 seat->in_gc_queue = false;
901
902 if (!seat_check_gc(seat, drop_not_started)) {
903 seat_stop(seat, false);
904 seat_free(seat);
905 }
906 }
907
908 while ((session = m->session_gc_queue)) {
909 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
910 session->in_gc_queue = false;
911
912 /* First, if we are not closing yet, initiate stopping */
913 if (!session_check_gc(session, drop_not_started) &&
914 session_get_state(session) != SESSION_CLOSING)
915 session_stop(session, false);
916
917 /* Normally, this should make the session busy again,
918 * if it doesn't then let's get rid of it
919 * immediately */
920 if (!session_check_gc(session, drop_not_started)) {
921 session_finalize(session);
922 session_free(session);
923 }
924 }
925
926 while ((user = m->user_gc_queue)) {
927 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
928 user->in_gc_queue = false;
929
930 /* First step: queue stop jobs */
931 if (!user_check_gc(user, drop_not_started))
932 user_stop(user, false);
933
934 /* Second step: finalize user */
935 if (!user_check_gc(user, drop_not_started)) {
936 user_finalize(user);
937 user_free(user);
938 }
939 }
940 }
941
942 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
943 Manager *m = userdata;
944 struct dual_timestamp since;
945 usec_t n, elapse;
946 int r;
947
948 assert(m);
949
950 if (m->idle_action == HANDLE_IGNORE ||
951 m->idle_action_usec <= 0)
952 return 0;
953
954 n = now(CLOCK_MONOTONIC);
955
956 r = manager_get_idle_hint(m, &since);
957 if (r <= 0)
958 /* Not idle. Let's check if after a timeout it might be idle then. */
959 elapse = n + m->idle_action_usec;
960 else {
961 /* Idle! Let's see if it's time to do something, or if
962 * we shall sleep for longer. */
963
964 if (n >= since.monotonic + m->idle_action_usec &&
965 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
966 log_info("System idle. Taking action.");
967
968 manager_handle_action(m, 0, m->idle_action, false, false);
969 m->idle_action_not_before_usec = n;
970 }
971
972 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
973 }
974
975 if (!m->idle_action_event_source) {
976
977 r = sd_event_add_time(
978 m->event,
979 &m->idle_action_event_source,
980 CLOCK_MONOTONIC,
981 elapse, USEC_PER_SEC*30,
982 manager_dispatch_idle_action, m);
983 if (r < 0)
984 return log_error_errno(r, "Failed to add idle event source: %m");
985
986 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
987 if (r < 0)
988 return log_error_errno(r, "Failed to set idle event source priority: %m");
989 } else {
990 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
991 if (r < 0)
992 return log_error_errno(r, "Failed to set idle event timer: %m");
993
994 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
995 if (r < 0)
996 return log_error_errno(r, "Failed to enable idle event timer: %m");
997 }
998
999 return 0;
1000 }
1001
1002 int manager_startup(Manager *m) {
1003 int r;
1004 Seat *seat;
1005 Session *session;
1006 User *user;
1007 Button *button;
1008 Inhibitor *inhibitor;
1009 Iterator i;
1010
1011 assert(m);
1012
1013 /* Connect to console */
1014 r = manager_connect_console(m);
1015 if (r < 0)
1016 return r;
1017
1018 /* Connect to udev */
1019 r = manager_connect_udev(m);
1020 if (r < 0)
1021 return log_error_errno(r, "Failed to create udev watchers: %m");
1022
1023 /* Connect to the bus */
1024 r = manager_connect_bus(m);
1025 if (r < 0)
1026 return r;
1027
1028 /* Instantiate magic seat 0 */
1029 r = manager_add_seat(m, "seat0", &m->seat0);
1030 if (r < 0)
1031 return log_error_errno(r, "Failed to add seat0: %m");
1032
1033 r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1034 if (r < 0)
1035 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1036
1037 /* Deserialize state */
1038 r = manager_enumerate_devices(m);
1039 if (r < 0)
1040 log_warning_errno(r, "Device enumeration failed: %m");
1041
1042 r = manager_enumerate_seats(m);
1043 if (r < 0)
1044 log_warning_errno(r, "Seat enumeration failed: %m");
1045
1046 r = manager_enumerate_users(m);
1047 if (r < 0)
1048 log_warning_errno(r, "User enumeration failed: %m");
1049
1050 r = manager_enumerate_sessions(m);
1051 if (r < 0)
1052 log_warning_errno(r, "Session enumeration failed: %m");
1053
1054 r = manager_enumerate_inhibitors(m);
1055 if (r < 0)
1056 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1057
1058 r = manager_enumerate_buttons(m);
1059 if (r < 0)
1060 log_warning_errno(r, "Button enumeration failed: %m");
1061
1062 /* Remove stale objects before we start them */
1063 manager_gc(m, false);
1064
1065 /* Reserve the special reserved VT */
1066 manager_reserve_vt(m);
1067
1068 /* And start everything */
1069 HASHMAP_FOREACH(seat, m->seats, i)
1070 seat_start(seat);
1071
1072 HASHMAP_FOREACH(user, m->users, i)
1073 user_start(user);
1074
1075 HASHMAP_FOREACH(session, m->sessions, i)
1076 session_start(session);
1077
1078 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1079 inhibitor_start(inhibitor);
1080
1081 HASHMAP_FOREACH(button, m->buttons, i)
1082 button_check_switches(button);
1083
1084 manager_dispatch_idle_action(NULL, 0, m);
1085
1086 return 0;
1087 }
1088
1089 int manager_run(Manager *m) {
1090 int r;
1091
1092 assert(m);
1093
1094 for (;;) {
1095 usec_t us = (uint64_t) -1;
1096
1097 r = sd_event_get_state(m->event);
1098 if (r < 0)
1099 return r;
1100 if (r == SD_EVENT_FINISHED)
1101 return 0;
1102
1103 manager_gc(m, true);
1104
1105 if (manager_dispatch_delayed(m) > 0)
1106 continue;
1107
1108 if (m->action_what != 0 && !m->action_job) {
1109 usec_t x, y;
1110
1111 x = now(CLOCK_MONOTONIC);
1112 y = m->action_timestamp + m->inhibit_delay_max;
1113
1114 us = x >= y ? 0 : y - x;
1115 }
1116
1117 r = sd_event_run(m->event, us);
1118 if (r < 0)
1119 return r;
1120 }
1121 }
1122
1123 static int manager_parse_config_file(Manager *m) {
1124 assert(m);
1125
1126 return config_parse_many("/etc/systemd/logind.conf",
1127 CONF_DIRS_NULSTR("systemd/logind.conf"),
1128 "Login\0",
1129 config_item_perf_lookup, logind_gperf_lookup,
1130 false, m);
1131 }
1132
1133 int main(int argc, char *argv[]) {
1134 Manager *m = NULL;
1135 int r;
1136
1137 log_set_target(LOG_TARGET_AUTO);
1138 log_set_facility(LOG_AUTH);
1139 log_parse_environment();
1140 log_open();
1141
1142 umask(0022);
1143
1144 if (argc != 1) {
1145 log_error("This program takes no arguments.");
1146 r = -EINVAL;
1147 goto finish;
1148 }
1149
1150 /* Always create the directories people can create inotify
1151 * watches in. Note that some applications might check for the
1152 * existence of /run/systemd/seats/ to determine whether
1153 * logind is available, so please always make sure this check
1154 * stays in. */
1155 mkdir_label("/run/systemd/seats", 0755);
1156 mkdir_label("/run/systemd/users", 0755);
1157 mkdir_label("/run/systemd/sessions", 0755);
1158
1159 m = manager_new();
1160 if (!m) {
1161 r = log_oom();
1162 goto finish;
1163 }
1164
1165 manager_parse_config_file(m);
1166
1167 r = manager_startup(m);
1168 if (r < 0) {
1169 log_error_errno(r, "Failed to fully start up daemon: %m");
1170 goto finish;
1171 }
1172
1173 log_debug("systemd-logind running as pid "PID_FMT, getpid());
1174
1175 sd_notify(false,
1176 "READY=1\n"
1177 "STATUS=Processing requests...");
1178
1179 r = manager_run(m);
1180
1181 log_debug("systemd-logind stopped as pid "PID_FMT, getpid());
1182
1183 finish:
1184 sd_notify(false,
1185 "STOPPING=1\n"
1186 "STATUS=Shutting down...");
1187
1188 if (m)
1189 manager_free(m);
1190
1191 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1192 }