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