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