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