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