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