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