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