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