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