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