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