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