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