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