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