chiark / gitweb /
Add some handling to remaining unlinkat calls
[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 "fs-util.h"
43 #include "logind.h"
44 //#include "process-util.h"
45 #include "selinux-util.h"
46 #include "signal-util.h"
47 #include "strv.h"
48 #include "udev-util.h"
49 /// Additional includes needed by elogind
50 #include "cgroup.h"       // From src/core/
51 #include "elogind.h"
52 #include "label.h"
53 #include "musl_missing.h"
54 #include "process-util.h"
55 #include "cgroup-util.h"
56
57 static void manager_free(Manager *m);
58
59 static void manager_reset_config(Manager *m) {
60 #if 0 /// elogind does not support autospawning of vts
61         m->n_autovts = 6;
62         m->reserve_vt = 6;
63 #endif // 0
64         m->remove_ipc = true;
65         m->inhibit_delay_max = 5 * USEC_PER_SEC;
66         m->handle_power_key = HANDLE_POWEROFF;
67         m->handle_suspend_key = HANDLE_SUSPEND;
68         m->handle_hibernate_key = HANDLE_HIBERNATE;
69         m->handle_lid_switch = HANDLE_SUSPEND;
70         m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
71         m->handle_lid_switch_docked = HANDLE_IGNORE;
72         m->power_key_ignore_inhibited = false;
73         m->suspend_key_ignore_inhibited = false;
74         m->hibernate_key_ignore_inhibited = false;
75         m->lid_switch_ignore_inhibited = true;
76
77         m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
78
79         m->idle_action_usec = 30 * USEC_PER_MINUTE;
80         m->idle_action = HANDLE_IGNORE;
81
82         m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
83         m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
84         m->sessions_max = 8192;
85         m->inhibitors_max = 8192;
86
87         m->kill_user_processes = KILL_USER_PROCESSES;
88
89         m->kill_only_users = strv_free(m->kill_only_users);
90         m->kill_exclude_users = strv_free(m->kill_exclude_users);
91 }
92
93 static Manager *manager_new(void) {
94         Manager *m;
95         int r;
96
97         m = new0(Manager, 1);
98         if (!m)
99                 return NULL;
100
101         m->console_active_fd = -1;
102 #if 0 /// UNNEEDED by elogind
103         m->reserve_vt_fd = -1;
104 #endif // 0
105
106         m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
107
108         m->devices = hashmap_new(&string_hash_ops);
109         m->seats = hashmap_new(&string_hash_ops);
110         m->sessions = hashmap_new(&string_hash_ops);
111         m->users = hashmap_new(NULL);
112         m->inhibitors = hashmap_new(&string_hash_ops);
113         m->buttons = hashmap_new(&string_hash_ops);
114
115         m->user_units = hashmap_new(&string_hash_ops);
116         m->session_units = hashmap_new(&string_hash_ops);
117
118         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
119                 goto fail;
120
121 #if 1 /// elogind needs some more data
122         r = elogind_manager_new(m);
123         if (r < 0)
124                 goto fail;
125 #endif // 1
126         m->udev = udev_new();
127         if (!m->udev)
128                 goto fail;
129
130         r = sd_event_default(&m->event);
131         if (r < 0)
132                 goto fail;
133
134         sd_event_set_watchdog(m->event, true);
135
136         manager_reset_config(m);
137
138         return m;
139
140 fail:
141         manager_free(m);
142         return NULL;
143 }
144
145 static void manager_free(Manager *m) {
146         Session *session;
147         User *u;
148         Device *d;
149         Seat *s;
150         Inhibitor *i;
151         Button *b;
152
153         if (!m)
154                 return;
155
156         while ((session = hashmap_first(m->sessions)))
157                 session_free(session);
158
159         while ((u = hashmap_first(m->users)))
160                 user_free(u);
161
162         while ((d = hashmap_first(m->devices)))
163                 device_free(d);
164
165         while ((s = hashmap_first(m->seats)))
166                 seat_free(s);
167
168         while ((i = hashmap_first(m->inhibitors)))
169                 inhibitor_free(i);
170
171         while ((b = hashmap_first(m->buttons)))
172                 button_free(b);
173
174         hashmap_free(m->devices);
175         hashmap_free(m->seats);
176         hashmap_free(m->sessions);
177         hashmap_free(m->users);
178         hashmap_free(m->inhibitors);
179         hashmap_free(m->buttons);
180
181         hashmap_free(m->user_units);
182         hashmap_free(m->session_units);
183
184         sd_event_source_unref(m->idle_action_event_source);
185         sd_event_source_unref(m->inhibit_timeout_source);
186         sd_event_source_unref(m->scheduled_shutdown_timeout_source);
187         sd_event_source_unref(m->nologin_timeout_source);
188         sd_event_source_unref(m->wall_message_timeout_source);
189
190         sd_event_source_unref(m->console_active_event_source);
191         sd_event_source_unref(m->udev_seat_event_source);
192         sd_event_source_unref(m->udev_device_event_source);
193         sd_event_source_unref(m->udev_vcsa_event_source);
194         sd_event_source_unref(m->udev_button_event_source);
195         sd_event_source_unref(m->lid_switch_ignore_event_source);
196
197         safe_close(m->console_active_fd);
198
199         udev_monitor_unref(m->udev_seat_monitor);
200         udev_monitor_unref(m->udev_device_monitor);
201         udev_monitor_unref(m->udev_vcsa_monitor);
202         udev_monitor_unref(m->udev_button_monitor);
203
204         udev_unref(m->udev);
205
206         if (m->unlink_nologin)
207                 (void) unlink_or_warn("/run/nologin");
208
209         bus_verify_polkit_async_registry_free(m->polkit_registry);
210
211         sd_bus_unref(m->bus);
212         sd_event_unref(m->event);
213
214 #if 0 /// elogind does not support autospawning of vts
215         safe_close(m->reserve_vt_fd);
216 #endif // 0
217 #if 1 /// elogind has to free its own data
218         elogind_manager_free(m);
219 #endif // 1
220
221         strv_free(m->kill_only_users);
222         strv_free(m->kill_exclude_users);
223
224         free(m->scheduled_shutdown_type);
225         free(m->scheduled_shutdown_tty);
226         free(m->wall_message);
227 #if 0 /// UNNEEDED by elogind
228         free(m->action_job);
229 #endif // 0
230         free(m);
231 }
232
233 static int manager_enumerate_devices(Manager *m) {
234         struct udev_list_entry *item = NULL, *first = NULL;
235         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
236         int r;
237
238         assert(m);
239
240         /* Loads devices from udev and creates seats for them as
241          * necessary */
242
243         e = udev_enumerate_new(m->udev);
244         if (!e)
245                 return -ENOMEM;
246
247         r = udev_enumerate_add_match_tag(e, "master-of-seat");
248         if (r < 0)
249                 return r;
250
251         r = udev_enumerate_add_match_is_initialized(e);
252         if (r < 0)
253                 return r;
254
255         r = udev_enumerate_scan_devices(e);
256         if (r < 0)
257                 return r;
258
259         first = udev_enumerate_get_list_entry(e);
260         udev_list_entry_foreach(item, first) {
261                 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
262                 int k;
263
264                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
265                 if (!d)
266                         return -ENOMEM;
267
268                 k = manager_process_seat_device(m, d);
269                 if (k < 0)
270                         r = k;
271         }
272
273         return r;
274 }
275
276 static int manager_enumerate_buttons(Manager *m) {
277         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
278         struct udev_list_entry *item = NULL, *first = NULL;
279         int r;
280
281         assert(m);
282
283         /* Loads buttons from udev */
284
285         if (manager_all_buttons_ignored(m))
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                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
354                                 log_warning("Failed to remove /run/systemd/seats/%s: %m",
355                                             de->d_name);
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 (!manager_all_buttons_ignored(m)) {
948                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
949                 if (!m->udev_button_monitor)
950                         return -ENOMEM;
951
952                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
953                 if (r < 0)
954                         return r;
955
956                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
957                 if (r < 0)
958                         return r;
959
960                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
961                 if (r < 0)
962                         return r;
963
964                 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);
965                 if (r < 0)
966                         return r;
967         }
968
969         /* Don't bother watching VCSA devices, if nobody cares */
970 #if 0 /// elogind does not support autospawning of vts
971         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
972
973                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
974                 if (!m->udev_vcsa_monitor)
975                         return -ENOMEM;
976
977                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
978                 if (r < 0)
979                         return r;
980
981                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
982                 if (r < 0)
983                         return r;
984
985                 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);
986                 if (r < 0)
987                         return r;
988         }
989 #endif // 0
990
991         return 0;
992 }
993
994 static void manager_gc(Manager *m, bool drop_not_started) {
995         Seat *seat;
996         Session *session;
997         User *user;
998
999         assert(m);
1000
1001         while ((seat = m->seat_gc_queue)) {
1002                 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
1003                 seat->in_gc_queue = false;
1004
1005                 if (!seat_check_gc(seat, drop_not_started)) {
1006                         seat_stop(seat, false);
1007                         seat_free(seat);
1008                 }
1009         }
1010
1011         while ((session = m->session_gc_queue)) {
1012                 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
1013                 session->in_gc_queue = false;
1014
1015                 /* First, if we are not closing yet, initiate stopping */
1016                 if (!session_check_gc(session, drop_not_started) &&
1017                     session_get_state(session) != SESSION_CLOSING)
1018                         session_stop(session, false);
1019
1020                 /* Normally, this should make the session referenced
1021                  * again, if it doesn't then let's get rid of it
1022                  * immediately */
1023                 if (!session_check_gc(session, drop_not_started)) {
1024                         session_finalize(session);
1025                         session_free(session);
1026                 }
1027         }
1028
1029         while ((user = m->user_gc_queue)) {
1030                 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
1031                 user->in_gc_queue = false;
1032
1033                 /* First step: queue stop jobs */
1034                 if (!user_check_gc(user, drop_not_started))
1035                         user_stop(user, false);
1036
1037                 /* Second step: finalize user */
1038                 if (!user_check_gc(user, drop_not_started)) {
1039                         user_finalize(user);
1040                         user_free(user);
1041                 }
1042         }
1043 }
1044
1045 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
1046         Manager *m = userdata;
1047         struct dual_timestamp since;
1048         usec_t n, elapse;
1049         int r;
1050
1051         assert(m);
1052
1053         if (m->idle_action == HANDLE_IGNORE ||
1054             m->idle_action_usec <= 0)
1055                 return 0;
1056
1057         n = now(CLOCK_MONOTONIC);
1058
1059         r = manager_get_idle_hint(m, &since);
1060         if (r <= 0)
1061                 /* Not idle. Let's check if after a timeout it might be idle then. */
1062                 elapse = n + m->idle_action_usec;
1063         else {
1064                 /* Idle! Let's see if it's time to do something, or if
1065                  * we shall sleep for longer. */
1066
1067                 if (n >= since.monotonic + m->idle_action_usec &&
1068                     (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1069                         log_info("System idle. Taking action.");
1070
1071                         manager_handle_action(m, 0, m->idle_action, false, false);
1072                         m->idle_action_not_before_usec = n;
1073                 }
1074
1075                 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
1076         }
1077
1078         if (!m->idle_action_event_source) {
1079
1080                 r = sd_event_add_time(
1081                                 m->event,
1082                                 &m->idle_action_event_source,
1083                                 CLOCK_MONOTONIC,
1084                                 elapse, USEC_PER_SEC*30,
1085                                 manager_dispatch_idle_action, m);
1086                 if (r < 0)
1087                         return log_error_errno(r, "Failed to add idle event source: %m");
1088
1089                 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
1090                 if (r < 0)
1091                         return log_error_errno(r, "Failed to set idle event source priority: %m");
1092         } else {
1093                 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1094                 if (r < 0)
1095                         return log_error_errno(r, "Failed to set idle event timer: %m");
1096
1097                 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1098                 if (r < 0)
1099                         return log_error_errno(r, "Failed to enable idle event timer: %m");
1100         }
1101
1102         return 0;
1103 }
1104
1105 static int manager_parse_config_file(Manager *m) {
1106 #if 0 /// elogind parses its own config file
1107         assert(m);
1108
1109         return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
1110                                         CONF_PATHS_NULSTR("systemd/logind.conf.d"),
1111                                         "Login\0",
1112                                         config_item_perf_lookup, logind_gperf_lookup,
1113 #else
1114          const char* logind_conf = getenv("ELOGIND_CONF_FILE");
1115
1116          assert(m);
1117
1118          if (!logind_conf)
1119                  logind_conf = PKGSYSCONFDIR "/logind.conf";
1120
1121          return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
1122                              config_item_perf_lookup, logind_gperf_lookup,
1123 #endif // 0
1124                                         CONFIG_PARSE_WARN, m);
1125 }
1126
1127 static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1128         Manager *m = userdata;
1129         int r;
1130
1131         manager_reset_config(m);
1132         r = manager_parse_config_file(m);
1133         if (r < 0)
1134                 log_warning_errno(r, "Failed to parse config file, using defaults: %m");
1135         else
1136                 log_info("Config file reloaded.");
1137
1138 #if 1 /// elogind needs an Add-On for sleep configuration
1139         elogind_manager_reset_config(m);
1140 #endif // 1
1141         return 0;
1142 }
1143
1144 static int manager_startup(Manager *m) {
1145         int r;
1146         Seat *seat;
1147         Session *session;
1148         User *user;
1149         Button *button;
1150         Inhibitor *inhibitor;
1151         Iterator i;
1152
1153         assert(m);
1154
1155         assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
1156
1157         r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
1158         if (r < 0)
1159                 return log_error_errno(r, "Failed to register SIGHUP handler: %m");
1160
1161 #if 1 /// elogind needs some extra preparations before connecting...
1162         elogind_manager_startup(m);
1163 #endif // 1
1164         /* Connect to console */
1165         r = manager_connect_console(m);
1166         if (r < 0)
1167                 return r;
1168
1169         /* Connect to udev */
1170         r = manager_connect_udev(m);
1171         if (r < 0)
1172                 return log_error_errno(r, "Failed to create udev watchers: %m");
1173
1174         /* Connect to the bus */
1175         r = manager_connect_bus(m);
1176         if (r < 0)
1177                 return r;
1178
1179         /* Instantiate magic seat 0 */
1180         r = manager_add_seat(m, "seat0", &m->seat0);
1181         if (r < 0)
1182                 return log_error_errno(r, "Failed to add seat0: %m");
1183
1184         r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1185         if (r < 0)
1186                 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1187
1188         /* Deserialize state */
1189         r = manager_enumerate_devices(m);
1190         if (r < 0)
1191                 log_warning_errno(r, "Device enumeration failed: %m");
1192
1193         r = manager_enumerate_seats(m);
1194         if (r < 0)
1195                 log_warning_errno(r, "Seat enumeration failed: %m");
1196
1197         r = manager_enumerate_users(m);
1198         if (r < 0)
1199                 log_warning_errno(r, "User enumeration failed: %m");
1200
1201         r = manager_enumerate_sessions(m);
1202         if (r < 0)
1203                 log_warning_errno(r, "Session enumeration failed: %m");
1204
1205         r = manager_enumerate_inhibitors(m);
1206         if (r < 0)
1207                 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1208
1209         r = manager_enumerate_buttons(m);
1210         if (r < 0)
1211                 log_warning_errno(r, "Button enumeration failed: %m");
1212
1213         /* Remove stale objects before we start them */
1214         manager_gc(m, false);
1215
1216         /* Reserve the special reserved VT */
1217 #if 0 /// elogind does not support autospawning of vts
1218         manager_reserve_vt(m);
1219 #endif // 0
1220
1221         /* And start everything */
1222         HASHMAP_FOREACH(seat, m->seats, i)
1223                 seat_start(seat);
1224
1225         HASHMAP_FOREACH(user, m->users, i)
1226                 user_start(user);
1227
1228         HASHMAP_FOREACH(session, m->sessions, i)
1229                 session_start(session);
1230
1231         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1232                 inhibitor_start(inhibitor);
1233
1234         HASHMAP_FOREACH(button, m->buttons, i)
1235                 button_check_switches(button);
1236
1237         manager_dispatch_idle_action(NULL, 0, m);
1238
1239         return 0;
1240 }
1241
1242 static int manager_run(Manager *m) {
1243         int r;
1244
1245         assert(m);
1246
1247         for (;;) {
1248                 r = sd_event_get_state(m->event);
1249                 if (r < 0)
1250                         return r;
1251                 if (r == SD_EVENT_FINISHED)
1252                         return 0;
1253
1254                 manager_gc(m, true);
1255
1256                 r = manager_dispatch_delayed(m, false);
1257                 if (r < 0)
1258                         return r;
1259                 if (r > 0)
1260                         continue;
1261
1262                 r = sd_event_run(m->event, (uint64_t) -1);
1263                 if (r < 0)
1264                         return r;
1265         }
1266 }
1267
1268 int main(int argc, char *argv[]) {
1269         Manager *m = NULL;
1270         int r;
1271
1272 #if 1 /// perform extra checks for elogind startup
1273         r = elogind_startup(argc, argv);
1274         if (r)
1275                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1276 #endif // 1
1277         elogind_set_program_name(argv[0]);
1278         log_set_target(LOG_TARGET_AUTO);
1279         log_set_facility(LOG_AUTH);
1280         log_parse_environment();
1281 #ifdef ENABLE_DEBUG_ELOGIND
1282         log_set_max_level(LOG_DEBUG);
1283         log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
1284 #endif // ENABLE_DEBUG_ELOGIND
1285         log_open();
1286
1287         umask(0022);
1288
1289 #if 0 /// elogind has some extra functionality at startup, argc can be != 1
1290         if (argc != 1) {
1291                 log_error("This program takes no arguments.");
1292                 r = -EINVAL;
1293                 goto finish;
1294         }
1295 #endif // 0
1296
1297         r = mac_selinux_init();
1298         if (r < 0) {
1299                 log_error_errno(r, "Could not initialize labelling: %m");
1300                 goto finish;
1301         }
1302
1303         /* Always create the directories people can create inotify
1304          * watches in. Note that some applications might check for the
1305          * existence of /run/systemd/seats/ to determine whether
1306          * logind is available, so please always make sure this check
1307          * stays in. */
1308 #if 0 /// elogind can not rely on systemd to help, so we need a bit more effort than this
1309         mkdir_label("/run/systemd/seats", 0755);
1310         mkdir_label("/run/systemd/users", 0755);
1311         mkdir_label("/run/systemd/sessions", 0755);
1312 #else
1313         r = mkdir_label("/run/systemd", 0755);
1314         if ( (r < 0) && (-EEXIST != r) )
1315                 return log_error_errno(r, "Failed to create /run/systemd : %m");
1316         r = mkdir_label("/run/systemd/seats", 0755);
1317         if ( r < 0 && (-EEXIST != r) )
1318                 return log_error_errno(r, "Failed to create /run/systemd/seats : %m");
1319         r = mkdir_label("/run/systemd/users", 0755);
1320         if ( r < 0 && (-EEXIST != r) )
1321                 return log_error_errno(r, "Failed to create /run/systemd/users : %m");
1322         r = mkdir_label("/run/systemd/sessions", 0755);
1323         if ( r < 0 && (-EEXIST != r) )
1324                 return log_error_errno(r, "Failed to create /run/systemd/sessions : %m");
1325         r = mkdir_label("/run/systemd/machines", 0755);
1326         if ( r < 0 && (-EEXIST != r) )
1327                 return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
1328 #endif // 0
1329
1330         m = manager_new();
1331         if (!m) {
1332                 r = log_oom();
1333                 goto finish;
1334         }
1335
1336         manager_parse_config_file(m);
1337
1338 #if 1 /// elogind needs an Add-On for sleep configuration
1339         elogind_manager_reset_config(m);
1340 #endif // 1
1341         r = manager_startup(m);
1342         if (r < 0) {
1343                 log_error_errno(r, "Failed to fully start up daemon: %m");
1344                 goto finish;
1345         }
1346
1347         log_debug("elogind running as pid "PID_FMT, getpid_cached());
1348
1349         sd_notify(false,
1350                   "READY=1\n"
1351                   "STATUS=Processing requests...");
1352
1353         r = manager_run(m);
1354
1355         log_debug("elogind stopped as pid "PID_FMT, getpid_cached());
1356
1357 finish:
1358         sd_notify(false,
1359                   "STOPPING=1\n"
1360                   "STATUS=Shutting down...");
1361
1362         manager_free(m);
1363
1364         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1365 }