chiark / gitweb /
Prep v238: Uncomment now needed headers and unmask now needed functions in src/login...
[elogind.git] / src / login / logind.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2011 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #if 0 /// elogind needs the systems udev header
27 #include "libudev.h"
28 #else
29 #include <libudev.h>
30 #endif // 0
31 #include "sd-daemon.h"
32
33 #include "alloc-util.h"
34 #include "bus-error.h"
35 #include "bus-util.h"
36 //#include "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                 if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
484                         log_debug("Device fd doesn't actually point to device node: %m");
485                         close_nointr(fd);
486                         continue;
487                 }
488
489                 sd = hashmap_get(s->devices, &st.st_rdev);
490                 if (!sd) {
491                         /* Weird, we got an fd for a session device which wasn't
492                         * recorded in the session state file... */
493                         log_warning("Got fd for missing session device [%u:%u] in session %s",
494                                     major(st.st_rdev), minor(st.st_rdev), s->id);
495                         close_nointr(fd);
496                         continue;
497                 }
498
499                 log_debug("Attaching fd to session device [%u:%u] for session %s",
500                           major(st.st_rdev), minor(st.st_rdev), s->id);
501
502                 session_device_attach_fd(sd, fd, s->was_active);
503         }
504
505         return 0;
506 }
507
508 static int manager_enumerate_sessions(Manager *m) {
509         _cleanup_closedir_ DIR *d = NULL;
510         struct dirent *de;
511         int r = 0, k;
512
513         assert(m);
514
515         /* Read in session data stored on disk */
516         d = opendir("/run/systemd/sessions");
517         if (!d) {
518                 if (errno == ENOENT)
519                         return 0;
520
521                 return log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
522         }
523
524         FOREACH_DIRENT(de, d, return -errno) {
525                 struct Session *s;
526
527                 if (!dirent_is_file(de))
528                         continue;
529
530                 if (!session_id_valid(de->d_name)) {
531                         log_warning("Invalid session file name '%s', ignoring.", de->d_name);
532                         r = -EINVAL;
533                         continue;
534                 }
535
536                 k = manager_add_session(m, de->d_name, &s);
537                 if (k < 0) {
538                         log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
539                         r = k;
540                         continue;
541                 }
542
543                 session_add_to_gc_queue(s);
544
545                 k = session_load(s);
546                 if (k < 0)
547                         r = k;
548         }
549
550         /* We might be restarted and PID1 could have sent us back the
551          * session device fds we previously saved. */
552         k = manager_attach_fds(m);
553         if (k < 0)
554                 log_warning_errno(k, "Failed to reattach session device fds: %m");
555
556         return r;
557 }
558
559 static int manager_enumerate_inhibitors(Manager *m) {
560         _cleanup_closedir_ DIR *d = NULL;
561         struct dirent *de;
562         int r = 0;
563
564         assert(m);
565
566         d = opendir("/run/systemd/inhibit");
567         if (!d) {
568                 if (errno == ENOENT)
569                         return 0;
570
571                 return log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
572         }
573
574         FOREACH_DIRENT(de, d, return -errno) {
575                 int k;
576                 Inhibitor *i;
577
578                 if (!dirent_is_file(de))
579                         continue;
580
581                 k = manager_add_inhibitor(m, de->d_name, &i);
582                 if (k < 0) {
583                         log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
584                         r = k;
585                         continue;
586                 }
587
588                 k = inhibitor_load(i);
589                 if (k < 0)
590                         r = k;
591         }
592
593         return r;
594 }
595
596 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
597         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
598         Manager *m = userdata;
599
600         assert(m);
601
602         d = udev_monitor_receive_device(m->udev_seat_monitor);
603         if (!d)
604                 return -ENOMEM;
605
606         manager_process_seat_device(m, d);
607         return 0;
608 }
609
610 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
611         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
612         Manager *m = userdata;
613
614         assert(m);
615
616         d = udev_monitor_receive_device(m->udev_device_monitor);
617         if (!d)
618                 return -ENOMEM;
619
620         manager_process_seat_device(m, d);
621         return 0;
622 }
623
624 #if 0 /// UNNEEDED by elogind
625 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
626         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
627         Manager *m = userdata;
628         const char *name;
629
630         assert(m);
631
632         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
633         if (!d)
634                 return -ENOMEM;
635
636         name = udev_device_get_sysname(d);
637
638         /* Whenever a VCSA device is removed try to reallocate our
639          * VTs, to make sure our auto VTs never go away. */
640
641         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
642                 seat_preallocate_vts(m->seat0);
643
644         return 0;
645 }
646 #endif // 0
647
648 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
649         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
650         Manager *m = userdata;
651
652         assert(m);
653
654         d = udev_monitor_receive_device(m->udev_button_monitor);
655         if (!d)
656                 return -ENOMEM;
657
658         manager_process_button_device(m, d);
659         return 0;
660 }
661
662 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
663         Manager *m = userdata;
664
665         assert(m);
666         assert(m->seat0);
667         assert(m->console_active_fd == fd);
668
669         seat_read_active_vt(m->seat0);
670         return 0;
671 }
672
673 #if 0 /// UNNEEDED by elogind
674 static int manager_reserve_vt(Manager *m) {
675         _cleanup_free_ char *p = NULL;
676
677         assert(m);
678
679         if (m->reserve_vt <= 0)
680                 return 0;
681
682         if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
683                 return log_oom();
684
685         m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
686         if (m->reserve_vt_fd < 0) {
687
688                 /* Don't complain on VT-less systems */
689                 if (errno != ENOENT)
690                         log_warning_errno(errno, "Failed to pin reserved VT: %m");
691                 return -errno;
692         }
693
694         return 0;
695 }
696 #endif // 0
697
698 static int manager_connect_bus(Manager *m) {
699         int r;
700
701         assert(m);
702         assert(!m->bus);
703
704         r = sd_bus_default_system(&m->bus);
705         if (r < 0)
706                 return log_error_errno(r, "Failed to connect to system bus: %m");
707
708         r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
709         if (r < 0)
710                 return log_error_errno(r, "Failed to add manager object vtable: %m");
711
712         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
713         if (r < 0)
714                 return log_error_errno(r, "Failed to add seat object vtable: %m");
715
716         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
717         if (r < 0)
718                 return log_error_errno(r, "Failed to add seat enumerator: %m");
719
720         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
721         if (r < 0)
722                 return log_error_errno(r, "Failed to add session object vtable: %m");
723
724         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
725         if (r < 0)
726                 return log_error_errno(r, "Failed to add session enumerator: %m");
727
728         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
729         if (r < 0)
730                 return log_error_errno(r, "Failed to add user object vtable: %m");
731
732         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
733         if (r < 0)
734                 return log_error_errno(r, "Failed to add user enumerator: %m");
735
736 #if 0 /// elogind does not support systemd as PID 1
737         r = sd_bus_match_signal_async(
738                         m->bus,
739                         NULL,
740                         "org.freedesktop.systemd1",
741                         "/org/freedesktop/systemd1",
742                         "org.freedesktop.systemd1.Manager",
743                         "JobRemoved",
744                         match_job_removed, NULL, m);
745         if (r < 0)
746                 return log_error_errno(r, "Failed to request match for JobRemoved: %m");
747
748         r = sd_bus_match_signal_async(
749                         m->bus,
750                         NULL,
751                         "org.freedesktop.systemd1",
752                         "/org/freedesktop/systemd1",
753                         "org.freedesktop.systemd1.Manager",
754                         "UnitRemoved",
755                         match_unit_removed, NULL, m);
756         if (r < 0)
757                 return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
758
759         r = sd_bus_match_signal_async(
760                         m->bus,
761                         NULL,
762                         "org.freedesktop.systemd1",
763                         NULL,
764                         "org.freedesktop.DBus.Properties",
765                         "PropertiesChanged",
766                         match_properties_changed, NULL, m);
767         if (r < 0)
768                 return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
769
770         r = sd_bus_match_signal_async(
771                         m->bus,
772                         NULL,
773                         "org.freedesktop.systemd1",
774                         "/org/freedesktop/systemd1",
775                         "org.freedesktop.systemd1.Manager",
776                         "Reloading",
777                         match_reloading, NULL, m);
778         if (r < 0)
779                 return log_error_errno(r, "Failed to request match for Reloading: %m");
780
781         r = sd_bus_call_method_async(
782                         m->bus,
783                         NULL,
784                         "org.freedesktop.systemd1",
785                         "/org/freedesktop/systemd1",
786                         "org.freedesktop.systemd1.Manager",
787                         "Subscribe",
788                         NULL, NULL,
789                         NULL);
790 #endif // 0
791         if (r < 0)
792                 return log_error_errno(r, "Failed to enable subscription: %m");
793
794         r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL);
795         if (r < 0)
796                 return log_error_errno(r, "Failed to request name: %m");
797
798         r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
799         if (r < 0)
800                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
801
802 #if 0 /// elogind has to setup its release agent
803         return 0;
804 #else
805         r = elogind_setup_cgroups_agent(m);
806
807         return r;
808 #endif // 0
809 }
810
811 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
812         Manager *m = data;
813         Session *active, *iter;
814
815         /*
816          * We got a VT-switch signal and we have to acknowledge it immediately.
817          * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
818          * old user-space might run multiple sessions on a single VT, *sigh*.
819          * Therefore, we have to iterate all sessions and find one with a vtfd
820          * on the requested VT.
821          * As only VTs with active controllers have VT_PROCESS set, our current
822          * notion of the active VT might be wrong (for instance if the switch
823          * happens while we setup VT_PROCESS). Therefore, read the current VT
824          * first and then use s->active->vtnr as reference. Note that this is
825          * not racy, as no further VT-switch can happen as long as we're in
826          * synchronous VT_PROCESS mode.
827          */
828
829         assert(m->seat0);
830         seat_read_active_vt(m->seat0);
831
832         active = m->seat0->active;
833         if (!active || active->vtnr < 1) {
834                 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
835                 return 0;
836         }
837
838         if (active->vtfd >= 0) {
839                 session_leave_vt(active);
840         } else {
841                 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
842                         if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
843                                 session_leave_vt(iter);
844                                 break;
845                         }
846                 }
847         }
848
849         return 0;
850 }
851
852 static int manager_connect_console(Manager *m) {
853         int r;
854
855         assert(m);
856         assert(m->console_active_fd < 0);
857
858         /* On certain architectures (S390 and Xen, and containers),
859            /dev/tty0 does not exist, so don't fail if we can't open
860            it. */
861         if (access("/dev/tty0", F_OK) < 0)
862                 return 0;
863
864         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
865         if (m->console_active_fd < 0) {
866
867                 /* On some systems the device node /dev/tty0 may exist
868                  * even though /sys/class/tty/tty0 does not. */
869                 if (errno == ENOENT)
870                         return 0;
871
872                 return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
873         }
874
875         r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
876         if (r < 0) {
877                 log_error("Failed to watch foreground console");
878                 return r;
879         }
880
881         /*
882          * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
883          * as VT-acquire signal. We ignore any acquire-events (yes, we still
884          * have to provide a valid signal-number for it!) and acknowledge all
885          * release events immediately.
886          */
887
888         if (SIGRTMIN + 1 > SIGRTMAX) {
889                 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
890                 return -EINVAL;
891         }
892
893         assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0);
894         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0);
895
896         r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
897         if (r < 0)
898                 return r;
899
900         return 0;
901 }
902
903 static int manager_connect_udev(Manager *m) {
904         int r;
905
906         assert(m);
907         assert(!m->udev_seat_monitor);
908         assert(!m->udev_device_monitor);
909         assert(!m->udev_vcsa_monitor);
910         assert(!m->udev_button_monitor);
911
912         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
913         if (!m->udev_seat_monitor)
914                 return -ENOMEM;
915
916         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
917         if (r < 0)
918                 return r;
919
920         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
921         if (r < 0)
922                 return r;
923
924         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);
925         if (r < 0)
926                 return r;
927
928         m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
929         if (!m->udev_device_monitor)
930                 return -ENOMEM;
931
932         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
933         if (r < 0)
934                 return r;
935
936         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
937         if (r < 0)
938                 return r;
939
940         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
941         if (r < 0)
942                 return r;
943
944         r = udev_monitor_enable_receiving(m->udev_device_monitor);
945         if (r < 0)
946                 return r;
947
948         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);
949         if (r < 0)
950                 return r;
951
952         /* Don't watch keys if nobody cares */
953         if (!manager_all_buttons_ignored(m)) {
954                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
955                 if (!m->udev_button_monitor)
956                         return -ENOMEM;
957
958                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
959                 if (r < 0)
960                         return r;
961
962                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
963                 if (r < 0)
964                         return r;
965
966                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
967                 if (r < 0)
968                         return r;
969
970                 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);
971                 if (r < 0)
972                         return r;
973         }
974
975         /* Don't bother watching VCSA devices, if nobody cares */
976 #if 0 /// elogind does not support autospawning of vts
977         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
978
979                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
980                 if (!m->udev_vcsa_monitor)
981                         return -ENOMEM;
982
983                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
984                 if (r < 0)
985                         return r;
986
987                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
988                 if (r < 0)
989                         return r;
990
991                 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);
992                 if (r < 0)
993                         return r;
994         }
995 #endif // 0
996
997         return 0;
998 }
999
1000 static void manager_gc(Manager *m, bool drop_not_started) {
1001         Seat *seat;
1002         Session *session;
1003         User *user;
1004
1005         assert(m);
1006
1007         while ((seat = m->seat_gc_queue)) {
1008                 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
1009                 seat->in_gc_queue = false;
1010
1011                 if (seat_may_gc(seat, drop_not_started)) {
1012                         seat_stop(seat, false);
1013                         seat_free(seat);
1014                 }
1015         }
1016
1017         while ((session = m->session_gc_queue)) {
1018                 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
1019                 session->in_gc_queue = false;
1020
1021                 /* First, if we are not closing yet, initiate stopping */
1022                 if (session_may_gc(session, drop_not_started) &&
1023                     session_get_state(session) != SESSION_CLOSING)
1024                         session_stop(session, false);
1025
1026                 /* Normally, this should make the session referenced
1027                  * again, if it doesn't then let's get rid of it
1028                  * immediately */
1029                 if (session_may_gc(session, drop_not_started)) {
1030                         session_finalize(session);
1031                         session_free(session);
1032                 }
1033         }
1034
1035         while ((user = m->user_gc_queue)) {
1036                 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
1037                 user->in_gc_queue = false;
1038
1039                 /* First step: queue stop jobs */
1040                 if (user_may_gc(user, drop_not_started))
1041                         user_stop(user, false);
1042
1043                 /* Second step: finalize user */
1044                 if (user_may_gc(user, drop_not_started)) {
1045                         user_finalize(user);
1046                         user_free(user);
1047                 }
1048         }
1049 }
1050
1051 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
1052         Manager *m = userdata;
1053         struct dual_timestamp since;
1054         usec_t n, elapse;
1055         int r;
1056
1057         assert(m);
1058
1059         if (m->idle_action == HANDLE_IGNORE ||
1060             m->idle_action_usec <= 0)
1061                 return 0;
1062
1063         n = now(CLOCK_MONOTONIC);
1064
1065         r = manager_get_idle_hint(m, &since);
1066         if (r <= 0)
1067                 /* Not idle. Let's check if after a timeout it might be idle then. */
1068                 elapse = n + m->idle_action_usec;
1069         else {
1070                 /* Idle! Let's see if it's time to do something, or if
1071                  * we shall sleep for longer. */
1072
1073                 if (n >= since.monotonic + m->idle_action_usec &&
1074                     (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1075                         log_info("System idle. Taking action.");
1076
1077                         manager_handle_action(m, 0, m->idle_action, false, false);
1078                         m->idle_action_not_before_usec = n;
1079                 }
1080
1081                 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
1082         }
1083
1084         if (!m->idle_action_event_source) {
1085
1086                 r = sd_event_add_time(
1087                                 m->event,
1088                                 &m->idle_action_event_source,
1089                                 CLOCK_MONOTONIC,
1090                                 elapse, USEC_PER_SEC*30,
1091                                 manager_dispatch_idle_action, m);
1092                 if (r < 0)
1093                         return log_error_errno(r, "Failed to add idle event source: %m");
1094
1095                 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
1096                 if (r < 0)
1097                         return log_error_errno(r, "Failed to set idle event source priority: %m");
1098         } else {
1099                 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1100                 if (r < 0)
1101                         return log_error_errno(r, "Failed to set idle event timer: %m");
1102
1103                 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1104                 if (r < 0)
1105                         return log_error_errno(r, "Failed to enable idle event timer: %m");
1106         }
1107
1108         return 0;
1109 }
1110
1111 static int manager_parse_config_file(Manager *m) {
1112 #if 0 /// elogind parses its own config file
1113         assert(m);
1114
1115         return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
1116                                         CONF_PATHS_NULSTR("systemd/logind.conf.d"),
1117                                         "Login\0",
1118                                         config_item_perf_lookup, logind_gperf_lookup,
1119 #else
1120          const char* logind_conf = getenv("ELOGIND_CONF_FILE");
1121
1122          assert(m);
1123
1124          if (!logind_conf)
1125                  logind_conf = PKGSYSCONFDIR "/logind.conf";
1126
1127          return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
1128                              config_item_perf_lookup, logind_gperf_lookup,
1129 #endif // 0
1130                                         CONFIG_PARSE_WARN, m);
1131 }
1132
1133 static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1134         Manager *m = userdata;
1135         int r;
1136
1137         manager_reset_config(m);
1138         r = manager_parse_config_file(m);
1139         if (r < 0)
1140                 log_warning_errno(r, "Failed to parse config file, using defaults: %m");
1141         else
1142                 log_info("Config file reloaded.");
1143
1144 #if 1 /// elogind needs an Add-On for sleep configuration
1145         elogind_manager_reset_config(m);
1146 #endif // 1
1147         return 0;
1148 }
1149
1150 static int manager_startup(Manager *m) {
1151         int r;
1152         Seat *seat;
1153         Session *session;
1154         User *user;
1155         Button *button;
1156         Inhibitor *inhibitor;
1157         Iterator i;
1158
1159         assert(m);
1160
1161         assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
1162
1163         r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
1164         if (r < 0)
1165                 return log_error_errno(r, "Failed to register SIGHUP handler: %m");
1166
1167 #if 1 /// elogind needs some extra preparations before connecting...
1168         elogind_manager_startup(m);
1169 #endif // 1
1170         /* Connect to console */
1171         r = manager_connect_console(m);
1172         if (r < 0)
1173                 return r;
1174
1175         /* Connect to udev */
1176         r = manager_connect_udev(m);
1177         if (r < 0)
1178                 return log_error_errno(r, "Failed to create udev watchers: %m");
1179
1180         /* Connect to the bus */
1181         r = manager_connect_bus(m);
1182         if (r < 0)
1183                 return r;
1184
1185         /* Instantiate magic seat 0 */
1186         r = manager_add_seat(m, "seat0", &m->seat0);
1187         if (r < 0)
1188                 return log_error_errno(r, "Failed to add seat0: %m");
1189
1190         r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1191         if (r < 0)
1192                 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1193
1194         /* Deserialize state */
1195         r = manager_enumerate_devices(m);
1196         if (r < 0)
1197                 log_warning_errno(r, "Device enumeration failed: %m");
1198
1199         r = manager_enumerate_seats(m);
1200         if (r < 0)
1201                 log_warning_errno(r, "Seat enumeration failed: %m");
1202
1203         r = manager_enumerate_users(m);
1204         if (r < 0)
1205                 log_warning_errno(r, "User enumeration failed: %m");
1206
1207         r = manager_enumerate_sessions(m);
1208         if (r < 0)
1209                 log_warning_errno(r, "Session enumeration failed: %m");
1210
1211         r = manager_enumerate_inhibitors(m);
1212         if (r < 0)
1213                 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1214
1215         r = manager_enumerate_buttons(m);
1216         if (r < 0)
1217                 log_warning_errno(r, "Button enumeration failed: %m");
1218
1219         /* Remove stale objects before we start them */
1220         manager_gc(m, false);
1221
1222         /* Reserve the special reserved VT */
1223 #if 0 /// elogind does not support autospawning of vts
1224         manager_reserve_vt(m);
1225 #endif // 0
1226
1227         /* And start everything */
1228         HASHMAP_FOREACH(seat, m->seats, i)
1229                 seat_start(seat);
1230
1231         HASHMAP_FOREACH(user, m->users, i)
1232                 user_start(user);
1233
1234         HASHMAP_FOREACH(session, m->sessions, i)
1235                 session_start(session);
1236
1237         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1238                 inhibitor_start(inhibitor);
1239
1240         HASHMAP_FOREACH(button, m->buttons, i)
1241                 button_check_switches(button);
1242
1243         manager_dispatch_idle_action(NULL, 0, m);
1244
1245         return 0;
1246 }
1247
1248 static int manager_run(Manager *m) {
1249         int r;
1250
1251         assert(m);
1252
1253         for (;;) {
1254                 r = sd_event_get_state(m->event);
1255                 if (r < 0)
1256                         return r;
1257                 if (r == SD_EVENT_FINISHED)
1258                         return 0;
1259
1260                 manager_gc(m, true);
1261
1262                 r = manager_dispatch_delayed(m, false);
1263                 if (r < 0)
1264                         return r;
1265                 if (r > 0)
1266                         continue;
1267
1268                 r = sd_event_run(m->event, (uint64_t) -1);
1269                 if (r < 0)
1270                         return r;
1271         }
1272 }
1273
1274 int main(int argc, char *argv[]) {
1275         Manager *m = NULL;
1276         int r;
1277
1278 #if 1 /// perform extra checks for elogind startup
1279         r = elogind_startup(argc, argv);
1280         if (r)
1281                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1282 #endif // 1
1283         elogind_set_program_name(argv[0]);
1284         log_set_target(LOG_TARGET_AUTO);
1285         log_set_facility(LOG_AUTH);
1286         log_parse_environment();
1287 #ifdef ENABLE_DEBUG_ELOGIND
1288         log_set_max_level(LOG_DEBUG);
1289         log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
1290 #endif // ENABLE_DEBUG_ELOGIND
1291         log_open();
1292
1293         umask(0022);
1294
1295 #if 0 /// elogind has some extra functionality at startup, argc can be != 1
1296         if (argc != 1) {
1297                 log_error("This program takes no arguments.");
1298                 r = -EINVAL;
1299                 goto finish;
1300         }
1301 #endif // 0
1302
1303         r = mac_selinux_init();
1304         if (r < 0) {
1305                 log_error_errno(r, "Could not initialize labelling: %m");
1306                 goto finish;
1307         }
1308
1309         /* Always create the directories people can create inotify
1310          * watches in. Note that some applications might check for the
1311          * existence of /run/systemd/seats/ to determine whether
1312          * logind is available, so please always make sure this check
1313          * stays in. */
1314 #if 0 /// elogind can not rely on systemd to help, so we need a bit more effort than this
1315         mkdir_label("/run/systemd/seats", 0755);
1316         mkdir_label("/run/systemd/users", 0755);
1317         mkdir_label("/run/systemd/sessions", 0755);
1318 #else
1319         r = mkdir_label("/run/systemd", 0755);
1320         if ( (r < 0) && (-EEXIST != r) )
1321                 return log_error_errno(r, "Failed to create /run/systemd : %m");
1322         r = mkdir_label("/run/systemd/seats", 0755);
1323         if ( r < 0 && (-EEXIST != r) )
1324                 return log_error_errno(r, "Failed to create /run/systemd/seats : %m");
1325         r = mkdir_label("/run/systemd/users", 0755);
1326         if ( r < 0 && (-EEXIST != r) )
1327                 return log_error_errno(r, "Failed to create /run/systemd/users : %m");
1328         r = mkdir_label("/run/systemd/sessions", 0755);
1329         if ( r < 0 && (-EEXIST != r) )
1330                 return log_error_errno(r, "Failed to create /run/systemd/sessions : %m");
1331         r = mkdir_label("/run/systemd/machines", 0755);
1332         if ( r < 0 && (-EEXIST != r) )
1333                 return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
1334 #endif // 0
1335
1336         m = manager_new();
1337         if (!m) {
1338                 r = log_oom();
1339                 goto finish;
1340         }
1341
1342         manager_parse_config_file(m);
1343
1344 #if 1 /// elogind needs an Add-On for sleep configuration
1345         elogind_manager_reset_config(m);
1346 #endif // 1
1347         r = manager_startup(m);
1348         if (r < 0) {
1349                 log_error_errno(r, "Failed to fully start up daemon: %m");
1350                 goto finish;
1351         }
1352
1353         log_debug("elogind running as pid "PID_FMT, getpid_cached());
1354
1355         sd_notify(false,
1356                   "READY=1\n"
1357                   "STATUS=Processing requests...");
1358
1359         r = manager_run(m);
1360
1361         log_debug("elogind stopped as pid "PID_FMT, getpid_cached());
1362
1363 finish:
1364         sd_notify(false,
1365                   "STOPPING=1\n"
1366                   "STATUS=Shutting down...");
1367
1368         manager_free(m);
1369
1370         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1371 }