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