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