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