chiark / gitweb /
fd17d80541e8dbd02fe28d454456dc48292bec7f
[elogind.git] / src / 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 General Public License as published by
10   the Free Software Foundation; either version 2 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   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <pwd.h>
24 #include <libudev.h>
25 #include <fcntl.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/epoll.h>
29 #include <sys/ioctl.h>
30 #include <linux/vt.h>
31
32 #include "logind.h"
33 #include "dbus-common.h"
34 #include "dbus-loop.h"
35 #include "strv.h"
36 #include "conf-parser.h"
37
38 Manager *manager_new(void) {
39         Manager *m;
40
41         m = new0(Manager, 1);
42         if (!m)
43                 return NULL;
44
45         m->console_active_fd = -1;
46         m->bus_fd = -1;
47         m->udev_seat_fd = -1;
48         m->udev_vcsa_fd = -1;
49         m->epoll_fd = -1;
50         m->n_autovts = 6;
51
52         m->devices = hashmap_new(string_hash_func, string_compare_func);
53         m->seats = hashmap_new(string_hash_func, string_compare_func);
54         m->sessions = hashmap_new(string_hash_func, string_compare_func);
55         m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
56         m->cgroups = hashmap_new(string_hash_func, string_compare_func);
57         m->fifo_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
58
59         if (!m->devices || !m->seats || !m->sessions || !m->users) {
60                 manager_free(m);
61                 return NULL;
62         }
63
64         m->udev = udev_new();
65         if (!m->udev) {
66                 manager_free(m);
67                 return NULL;
68         }
69
70         if (cg_get_user_path(&m->cgroup_path) < 0) {
71                 manager_free(m);
72                 return NULL;
73         }
74
75         return m;
76 }
77
78 void manager_free(Manager *m) {
79         Session *session;
80         User *u;
81         Device *d;
82         Seat *s;
83
84         assert(m);
85
86         while ((session = hashmap_first(m->sessions)))
87                 session_free(session);
88
89         while ((u = hashmap_first(m->users)))
90                 user_free(u);
91
92         while ((d = hashmap_first(m->devices)))
93                 device_free(d);
94
95         while ((s = hashmap_first(m->seats)))
96                 seat_free(s);
97
98         hashmap_free(m->sessions);
99         hashmap_free(m->users);
100         hashmap_free(m->devices);
101         hashmap_free(m->seats);
102         hashmap_free(m->cgroups);
103         hashmap_free(m->fifo_fds);
104
105         if (m->console_active_fd >= 0)
106                 close_nointr_nofail(m->console_active_fd);
107
108         if (m->udev_seat_monitor)
109                 udev_monitor_unref(m->udev_seat_monitor);
110
111         if (m->udev_vcsa_monitor)
112                 udev_monitor_unref(m->udev_vcsa_monitor);
113
114         if (m->udev)
115                 udev_unref(m->udev);
116
117         if (m->bus) {
118                 dbus_connection_flush(m->bus);
119                 dbus_connection_close(m->bus);
120                 dbus_connection_unref(m->bus);
121         }
122
123         if (m->bus_fd >= 0)
124                 close_nointr_nofail(m->bus_fd);
125
126         if (m->epoll_fd >= 0)
127                 close_nointr_nofail(m->epoll_fd);
128
129         strv_free(m->controllers);
130         strv_free(m->reset_controllers);
131         strv_free(m->kill_only_users);
132         strv_free(m->kill_exclude_users);
133
134         free(m->cgroup_path);
135         free(m);
136 }
137
138 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
139         Device *d;
140
141         assert(m);
142         assert(sysfs);
143
144         d = hashmap_get(m->devices, sysfs);
145         if (d) {
146                 if (_device)
147                         *_device = d;
148
149                 return 0;
150         }
151
152         d = device_new(m, sysfs);
153         if (!d)
154                 return -ENOMEM;
155
156         if (_device)
157                 *_device = d;
158
159         return 0;
160 }
161
162 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
163         Seat *s;
164
165         assert(m);
166         assert(id);
167
168         s = hashmap_get(m->seats, id);
169         if (s) {
170                 if (_seat)
171                         *_seat = s;
172
173                 return 0;
174         }
175
176         s = seat_new(m, id);
177         if (!s)
178                 return -ENOMEM;
179
180         if (_seat)
181                 *_seat = s;
182
183         return 0;
184 }
185
186 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
187         Session *s;
188
189         assert(m);
190         assert(id);
191
192         s = hashmap_get(m->sessions, id);
193         if (s) {
194                 if (_session)
195                         *_session = s;
196
197                 return 0;
198         }
199
200         s = session_new(m, u, id);
201         if (!s)
202                 return -ENOMEM;
203
204         if (_session)
205                 *_session = s;
206
207         return 0;
208 }
209
210 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
211         User *u;
212
213         assert(m);
214         assert(name);
215
216         u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
217         if (u) {
218                 if (_user)
219                         *_user = u;
220
221                 return 0;
222         }
223
224         u = user_new(m, uid, gid, name);
225         if (!u)
226                 return -ENOMEM;
227
228         if (_user)
229                 *_user = u;
230
231         return 0;
232 }
233
234 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
235         struct passwd *p;
236
237         assert(m);
238         assert(name);
239
240         errno = 0;
241         p = getpwnam(name);
242         if (!p)
243                 return errno ? -errno : -ENOENT;
244
245         return manager_add_user(m, p->pw_uid, p->pw_gid, name, _user);
246 }
247
248 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
249         struct passwd *p;
250
251         assert(m);
252
253         errno = 0;
254         p = getpwuid(uid);
255         if (!p)
256                 return errno ? -errno : -ENOENT;
257
258         return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
259 }
260
261 int manager_process_seat_device(Manager *m, struct udev_device *d) {
262         Device *device;
263         int r;
264
265         assert(m);
266
267         /* FIXME: drop this check as soon as libudev's enum support
268          * honours tags and subsystem matches at the same time */
269         if (!streq_ptr(udev_device_get_subsystem(d), "graphics"))
270                 return 0;
271
272         if (streq_ptr(udev_device_get_action(d), "remove")) {
273
274                 /* FIXME: use syspath instead of sysname here, as soon as fb driver is fixed */
275                 device = hashmap_get(m->devices, udev_device_get_sysname(d));
276                 if (!device)
277                         return 0;
278
279                 seat_add_to_gc_queue(device->seat);
280                 device_free(device);
281
282         } else {
283                 const char *sn;
284                 Seat *seat;
285
286                 sn = udev_device_get_property_value(d, "ID_SEAT");
287                 if (!sn)
288                         sn = "seat0";
289
290                 if (!seat_name_is_valid(sn)) {
291                         log_warning("Device with invalid seat name %s found, ignoring.", sn);
292                         return 0;
293                 }
294
295                 r = manager_add_device(m, udev_device_get_sysname(d), &device);
296                 if (r < 0)
297                         return r;
298
299                 r = manager_add_seat(m, sn, &seat);
300                 if (r < 0) {
301                         if (!device->seat)
302                                 device_free(device);
303
304                         return r;
305                 }
306
307                 device_attach(device, seat);
308                 seat_start(seat);
309         }
310
311         return 0;
312 }
313
314 int manager_enumerate_devices(Manager *m) {
315         struct udev_list_entry *item = NULL, *first = NULL;
316         struct udev_enumerate *e;
317         int r;
318
319         assert(m);
320
321         /* Loads devices from udev and creates seats for them as
322          * necessary */
323
324         e = udev_enumerate_new(m->udev);
325         if (!e) {
326                 r = -ENOMEM;
327                 goto finish;
328         }
329
330         r = udev_enumerate_add_match_subsystem(e, "graphics");
331         if (r < 0)
332                 goto finish;
333
334         r = udev_enumerate_add_match_tag(e, "seat");
335         if (r < 0)
336                 goto finish;
337
338         r = udev_enumerate_scan_devices(e);
339         if (r < 0)
340                 goto finish;
341
342         first = udev_enumerate_get_list_entry(e);
343         udev_list_entry_foreach(item, first) {
344                 struct udev_device *d;
345                 int k;
346
347                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
348                 if (!d) {
349                         r = -ENOMEM;
350                         goto finish;
351                 }
352
353                 k = manager_process_seat_device(m, d);
354                 udev_device_unref(d);
355
356                 if (k < 0)
357                         r = k;
358         }
359
360 finish:
361         if (e)
362                 udev_enumerate_unref(e);
363
364         return r;
365 }
366
367 int manager_enumerate_seats(Manager *m) {
368         DIR *d;
369         struct dirent *de;
370         int r = 0;
371
372         assert(m);
373
374         /* This loads data about seats stored on disk, but does not
375          * actually create any seats. Removes data of seats that no
376          * longer exist. */
377
378         d = opendir("/run/systemd/seats");
379         if (!d) {
380                 if (errno == ENOENT)
381                         return 0;
382
383                 log_error("Failed to open /run/systemd/seats: %m");
384                 return -errno;
385         }
386
387         while ((de = readdir(d))) {
388                 Seat *s;
389                 int k;
390
391                 if (!dirent_is_file(de))
392                         continue;
393
394                 s = hashmap_get(m->seats, de->d_name);
395                 if (!s) {
396                         unlinkat(dirfd(d), de->d_name, 0);
397                         continue;
398                 }
399
400                 k = seat_load(s);
401                 if (k < 0)
402                         r = k;
403         }
404
405         closedir(d);
406
407         return r;
408 }
409
410 static int manager_enumerate_users_from_cgroup(Manager *m) {
411         int r = 0;
412         char *name;
413         DIR *d;
414
415         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
416         if (r < 0) {
417                 if (r == -ENOENT)
418                         return 0;
419
420                 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
421                 return r;
422         }
423
424         while ((r = cg_read_subgroup(d, &name)) > 0) {
425                 User *user;
426                 int k;
427
428                 k = manager_add_user_by_name(m, name, &user);
429                 if (k < 0) {
430                         free(name);
431                         r = k;
432                         continue;
433                 }
434
435                 user_add_to_gc_queue(user);
436
437                 if (!user->cgroup_path)
438                         if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
439                                 r = -ENOMEM;
440                                 free(name);
441                                 break;
442                         }
443
444                 free(name);
445         }
446
447         closedir(d);
448
449         return r;
450 }
451
452
453 static int manager_enumerate_linger_users(Manager *m) {
454         DIR *d;
455         struct dirent *de;
456         int r = 0;
457
458         d = opendir("/var/lib/systemd/linger");
459         if (!d) {
460                 if (errno == ENOENT)
461                         return 0;
462
463                 log_error("Failed to open /var/lib/systemd/linger/: %m");
464                 return -errno;
465         }
466
467         while ((de = readdir(d))) {
468                 int k;
469
470                 if (!dirent_is_file(de))
471                         continue;
472
473                 k = manager_add_user_by_name(m, de->d_name, NULL);
474                 if (k < 0) {
475                         log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
476                         r = k;
477                 }
478         }
479
480         closedir(d);
481
482         return r;
483 }
484
485 int manager_enumerate_users(Manager *m) {
486         DIR *d;
487         struct dirent *de;
488         int r, k;
489
490         assert(m);
491
492         /* First, enumerate user cgroups */
493         r = manager_enumerate_users_from_cgroup(m);
494
495         /* Second, add lingering users on top */
496         k = manager_enumerate_linger_users(m);
497         if (k < 0)
498                 r = k;
499
500         /* Third, read in user data stored on disk */
501         d = opendir("/run/systemd/users");
502         if (!d) {
503                 if (errno == ENOENT)
504                         return 0;
505
506                 log_error("Failed to open /run/systemd/users: %m");
507                 return -errno;
508         }
509
510         while ((de = readdir(d))) {
511                 unsigned long ul;
512                 User *u;
513
514                 if (!dirent_is_file(de))
515                         continue;
516
517                 k = safe_atolu(de->d_name, &ul);
518                 if (k < 0) {
519                         log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
520                         continue;
521                 }
522
523                 u = hashmap_get(m->users, ULONG_TO_PTR(ul));
524                 if (!u) {
525                         unlinkat(dirfd(d), de->d_name, 0);
526                         continue;
527                 }
528
529                 k = user_load(u);
530                 if (k < 0)
531                         r = k;
532         }
533
534         closedir(d);
535
536         return r;
537 }
538
539 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
540         User *u;
541         Iterator i;
542         int r = 0;
543
544         HASHMAP_FOREACH(u, m->users, i) {
545                 DIR *d;
546                 char *name;
547                 int k;
548
549                 if (!u->cgroup_path)
550                         continue;
551
552                 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
553                 if (k < 0) {
554                         if (k == -ENOENT)
555                                 continue;
556
557                         log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
558                         r = k;
559                         continue;
560                 }
561
562                 while ((k = cg_read_subgroup(d, &name)) > 0) {
563                         Session *session;
564
565                         k = manager_add_session(m, u, name, &session);
566                         if (k < 0) {
567                                 free(name);
568                                 break;
569                         }
570
571                         session_add_to_gc_queue(session);
572
573                         if (!session->cgroup_path)
574                                 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
575                                         k = -ENOMEM;
576                                         free(name);
577                                         break;
578                                 }
579
580                         free(name);
581                 }
582
583                 closedir(d);
584
585                 if (k < 0)
586                         r = k;
587         }
588
589         return r;
590 }
591
592 int manager_enumerate_sessions(Manager *m) {
593         DIR *d;
594         struct dirent *de;
595         int r = 0;
596
597         assert(m);
598
599         /* First enumerate session cgroups */
600         r = manager_enumerate_sessions_from_cgroup(m);
601
602         /* Second, read in session data stored on disk */
603         d = opendir("/run/systemd/sessions");
604         if (!d) {
605                 if (errno == ENOENT)
606                         return 0;
607
608                 log_error("Failed to open /run/systemd/sessions: %m");
609                 return -errno;
610         }
611
612         while ((de = readdir(d))) {
613                 struct Session *s;
614                 int k;
615
616                 if (!dirent_is_file(de))
617                         continue;
618
619                 s = hashmap_get(m->sessions, de->d_name);
620                 if (!s) {
621                         unlinkat(dirfd(d), de->d_name, 0);
622                         continue;
623                 }
624
625                 k = session_load(s);
626                 if (k < 0)
627                         r = k;
628         }
629
630         closedir(d);
631
632         return r;
633 }
634
635 int manager_dispatch_seat_udev(Manager *m) {
636         struct udev_device *d;
637         int r;
638
639         assert(m);
640
641         d = udev_monitor_receive_device(m->udev_seat_monitor);
642         if (!d)
643                 return -ENOMEM;
644
645         r = manager_process_seat_device(m, d);
646         udev_device_unref(d);
647
648         return r;
649 }
650
651
652 int manager_dispatch_vcsa_udev(Manager *m) {
653         struct udev_device *d;
654         int r = 0;
655         const char *name;
656
657         assert(m);
658
659         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
660         if (!d)
661                 return -ENOMEM;
662
663         name = udev_device_get_sysname(d);
664
665         /* Whenever a VCSA device is removed try to reallocate our
666          * VTs, to make sure our auto VTs never go away. */
667
668         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
669                 r = seat_preallocate_vts(m->vtconsole);
670
671         udev_device_unref(d);
672
673         return r;
674 }
675
676 int manager_dispatch_console(Manager *m) {
677         assert(m);
678
679         if (m->vtconsole)
680                 seat_read_active_vt(m->vtconsole);
681
682         return 0;
683 }
684
685 static int vt_is_busy(int vtnr) {
686         struct vt_stat vt_stat;
687         int r = 0, fd;
688
689         assert(vtnr >= 1);
690
691         /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
692          * we'd open the latter we'd open the foreground tty which
693          * hence would be unconditionally busy. By opening /dev/tty1
694          * we avoid this. Since tty1 is special and needs to be an
695          * explicitly loaded getty or DM this is safe. */
696
697         fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
698         if (fd < 0)
699                 return -errno;
700
701         if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
702                 r = -errno;
703         else
704                 r = !!(vt_stat.v_state & (1 << vtnr));
705
706         close_nointr_nofail(fd);
707
708         return r;
709 }
710
711 int manager_spawn_autovt(Manager *m, int vtnr) {
712         int r;
713         DBusMessage *message = NULL, *reply = NULL;
714         char *name = NULL;
715         const char *mode = "fail";
716         DBusError error;
717
718         assert(m);
719         assert(vtnr >= 1);
720
721         dbus_error_init(&error);
722
723         if ((unsigned) vtnr > m->n_autovts)
724                 return 0;
725
726         r = vt_is_busy(vtnr);
727         if (r < 0)
728                 return r;
729         else if (r > 0)
730                 return -EBUSY;
731
732         message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
733         if (!message) {
734                 log_error("Could not allocate message.");
735                 r = -ENOMEM;
736                 goto finish;
737         }
738
739         if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
740                 log_error("Could not allocate service name.");
741                 r = -ENOMEM;
742                 goto finish;
743         }
744
745         if (!dbus_message_append_args(message,
746                                       DBUS_TYPE_STRING, &name,
747                                       DBUS_TYPE_STRING, &mode,
748                                       DBUS_TYPE_INVALID)) {
749                 log_error("Could not attach target and flag information to message.");
750                 r = -ENOMEM;
751                 goto finish;
752         }
753
754         reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
755         if (!reply) {
756                 log_error("Failed to start unit: %s", bus_error_message(&error));
757                 goto finish;
758         }
759
760         r = 0;
761
762 finish:
763         free(name);
764
765         if (message)
766                 dbus_message_unref(message);
767
768         if (reply)
769                 dbus_message_unref(reply);
770
771         dbus_error_free(&error);
772
773         return r;
774 }
775
776 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
777         Session *s;
778         char *p;
779
780         assert(m);
781         assert(cgroup);
782
783         p = strdup(cgroup);
784         if (!p) {
785                 log_error("Out of memory.");
786                 return;
787         }
788
789         for (;;) {
790                 char *e;
791
792                 if (isempty(p) || streq(p, "/"))
793                         break;
794
795                 s = hashmap_get(m->cgroups, p);
796                 if (s)
797                         session_add_to_gc_queue(s);
798
799                 assert_se(e = strrchr(p, '/'));
800                 *e = 0;
801         }
802
803         free(p);
804 }
805
806 static void manager_pipe_notify_eof(Manager *m, int fd) {
807         Session *s;
808
809         assert_se(m);
810         assert_se(fd >= 0);
811
812         assert_se(s = hashmap_get(m->fifo_fds, INT_TO_PTR(fd + 1)));
813         assert(s->fifo_fd == fd);
814         session_remove_fifo(s);
815
816         session_stop(s);
817 }
818
819 static int manager_connect_bus(Manager *m) {
820         DBusError error;
821         int r;
822         struct epoll_event ev;
823
824         assert(m);
825         assert(!m->bus);
826         assert(m->bus_fd < 0);
827
828         dbus_error_init(&error);
829
830         m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
831         if (!m->bus) {
832                 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
833                 r = -ECONNREFUSED;
834                 goto fail;
835         }
836
837         if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
838             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
839             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
840             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
841             !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
842                 log_error("Not enough memory");
843                 r = -ENOMEM;
844                 goto fail;
845         }
846
847         dbus_bus_add_match(m->bus,
848                            "type='signal',"
849                            "interface='org.freedesktop.systemd1.Agent',"
850                            "member='Released',"
851                            "path='/org/freedesktop/systemd1/agent'",
852                            &error);
853
854         if (dbus_error_is_set(&error)) {
855                 log_error("Failed to register match: %s", bus_error_message(&error));
856                 r = -EIO;
857                 goto fail;
858         }
859
860         r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
861         if (dbus_error_is_set(&error)) {
862                 log_error("Failed to register name on bus: %s", bus_error_message(&error));
863                 r = -EIO;
864                 goto fail;
865         }
866
867         if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {
868                 log_error("Failed to acquire name.");
869                 r = -EEXIST;
870                 goto fail;
871         }
872
873         m->bus_fd = bus_loop_open(m->bus);
874         if (m->bus_fd < 0) {
875                 r = m->bus_fd;
876                 goto fail;
877         }
878
879         zero(ev);
880         ev.events = EPOLLIN;
881         ev.data.u32 = FD_BUS;
882
883         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
884                 goto fail;
885
886         return 0;
887
888 fail:
889         dbus_error_free(&error);
890
891         return r;
892 }
893
894 static int manager_connect_console(Manager *m) {
895         struct epoll_event ev;
896
897         assert(m);
898         assert(m->console_active_fd < 0);
899
900         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
901         if (m->console_active_fd < 0) {
902                 log_error("Failed to open /sys/class/tty/tty0/active: %m");
903                 return -errno;
904         }
905
906         zero(ev);
907         ev.events = 0;
908         ev.data.u32 = FD_CONSOLE;
909
910         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
911                 return -errno;
912
913         return 0;
914 }
915
916 static int manager_connect_udev(Manager *m) {
917         struct epoll_event ev;
918         int r;
919
920         assert(m);
921         assert(!m->udev_seat_monitor);
922         assert(!m->udev_vcsa_monitor);
923
924         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
925         if (!m->udev_seat_monitor)
926                 return -ENOMEM;
927
928         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
929         if (r < 0)
930                 return r;
931
932         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
933         if (r < 0)
934                 return r;
935
936         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
937         if (r < 0)
938                 return r;
939
940         m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
941
942         zero(ev);
943         ev.events = EPOLLIN;
944         ev.data.u32 = FD_SEAT_UDEV;
945
946         if (m->n_autovts <= 0)
947                 return 0;
948
949         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
950                 return -errno;
951
952         m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
953         if (!m->udev_vcsa_monitor)
954                 return -ENOMEM;
955
956         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
957         if (r < 0)
958                 return r;
959
960         r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
961         if (r < 0)
962                 return r;
963
964         m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
965
966         zero(ev);
967         ev.events = EPOLLIN;
968         ev.data.u32 = FD_VCSA_UDEV;
969
970         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
971                 return -errno;
972
973         return 0;
974 }
975
976 void manager_gc(Manager *m) {
977         Seat *seat;
978         Session *session;
979         User *user;
980
981         assert(m);
982
983         while ((seat = m->seat_gc_queue)) {
984                 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
985                 seat->in_gc_queue = false;
986
987                 if (seat_check_gc(seat) == 0) {
988                         seat_stop(seat);
989                         seat_free(seat);
990                 }
991         }
992
993         while ((session = m->session_gc_queue)) {
994                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
995                 session->in_gc_queue = false;
996
997                 if (session_check_gc(session) == 0) {
998                         session_stop(session);
999                         session_free(session);
1000                 }
1001         }
1002
1003         while ((user = m->user_gc_queue)) {
1004                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1005                 user->in_gc_queue = false;
1006
1007                 if (user_check_gc(user) == 0) {
1008                         user_stop(user);
1009                         user_free(user);
1010                 }
1011         }
1012 }
1013
1014 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1015         Session *s;
1016         bool idle_hint = true;
1017         dual_timestamp ts = { 0, 0 };
1018         Iterator i;
1019
1020         assert(m);
1021
1022         HASHMAP_FOREACH(s, m->sessions, i) {
1023                 dual_timestamp k;
1024                 int ih;
1025
1026                 ih = session_get_idle_hint(s, &k);
1027                 if (ih < 0)
1028                         return ih;
1029
1030                 if (!ih) {
1031                         if (!idle_hint) {
1032                                 if (k.monotonic < ts.monotonic)
1033                                         ts = k;
1034                         } else {
1035                                 idle_hint = false;
1036                                 ts = k;
1037                         }
1038                 } else if (idle_hint) {
1039
1040                         if (k.monotonic > ts.monotonic)
1041                                 ts = k;
1042                 }
1043         }
1044
1045         if (t)
1046                 *t = ts;
1047
1048         return idle_hint;
1049 }
1050
1051 int manager_startup(Manager *m) {
1052         int r;
1053         Seat *seat;
1054         Session *session;
1055         User *user;
1056         Iterator i;
1057
1058         assert(m);
1059         assert(m->epoll_fd <= 0);
1060
1061         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1062         if (m->epoll_fd < 0)
1063                 return -errno;
1064
1065         /* Connect to udev */
1066         r = manager_connect_udev(m);
1067         if (r < 0)
1068                 return r;
1069
1070         /* Connect to console */
1071         r = manager_connect_console(m);
1072         if (r < 0)
1073                 return r;
1074
1075         /* Connect to the bus */
1076         r = manager_connect_bus(m);
1077         if (r < 0)
1078                 return r;
1079
1080         /* Instantiate magic seat 0 */
1081         r = manager_add_seat(m, "seat0", &m->vtconsole);
1082         if (r < 0)
1083                 return r;
1084
1085         /* Deserialize state */
1086         manager_enumerate_devices(m);
1087         manager_enumerate_seats(m);
1088         manager_enumerate_users(m);
1089         manager_enumerate_sessions(m);
1090
1091         /* And start everything */
1092         HASHMAP_FOREACH(seat, m->seats, i)
1093                 seat_start(seat);
1094
1095         HASHMAP_FOREACH(user, m->users, i)
1096                 user_start(user);
1097
1098         HASHMAP_FOREACH(session, m->sessions, i)
1099                 session_start(session);
1100
1101         return 0;
1102 }
1103
1104 int manager_run(Manager *m) {
1105         assert(m);
1106
1107         for (;;) {
1108                 struct epoll_event event;
1109                 int n;
1110
1111                 manager_gc(m);
1112
1113                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1114                         continue;
1115
1116                 manager_gc(m);
1117
1118                 n = epoll_wait(m->epoll_fd, &event, 1, -1);
1119                 if (n < 0) {
1120                         if (errno == EINTR || errno == EAGAIN)
1121                                 continue;
1122
1123                         log_error("epoll() failed: %m");
1124                         return -errno;
1125                 }
1126
1127                 switch (event.data.u32) {
1128
1129                 case FD_SEAT_UDEV:
1130                         manager_dispatch_seat_udev(m);
1131                         break;
1132
1133                 case FD_VCSA_UDEV:
1134                         manager_dispatch_vcsa_udev(m);
1135                         break;
1136
1137                 case FD_CONSOLE:
1138                         manager_dispatch_console(m);
1139                         break;
1140
1141                 case FD_BUS:
1142                         bus_loop_dispatch(m->bus_fd);
1143                         break;
1144
1145                 default:
1146                         if (event.data.u32 >= FD_FIFO_BASE)
1147                                 manager_pipe_notify_eof(m, event.data.u32 - FD_FIFO_BASE);
1148                 }
1149         }
1150
1151         return 0;
1152 }
1153
1154 static int manager_parse_config_file(Manager *m) {
1155
1156         const ConfigItem items[] = {
1157                 { "NAutoVTs",          config_parse_unsigned, 0, &m->n_autovts,           "Login" },
1158                 { "KillUserProcesses", config_parse_bool,     0, &m->kill_user_processes, "Login" },
1159                 { "KilOnlyUsers",      config_parse_strv,     0, &m->kill_only_users,     "Login" },
1160                 { "KillExcludeUsers",  config_parse_strv,     0, &m->kill_exclude_users,  "Login" },
1161                 { "Controllers",       config_parse_strv,     0, &m->controllers,         "Login" },
1162                 { "ResetControllers",  config_parse_strv,     0, &m->reset_controllers,   "Login" },
1163                 { NULL, NULL, 0, NULL, NULL }
1164         };
1165
1166         static const char * const sections[] = {
1167                 "Login",
1168                 NULL
1169         };
1170
1171         FILE *f;
1172         const char *fn;
1173         int r;
1174
1175         assert(m);
1176
1177         fn = "/etc/systemd/systemd-logind.conf";
1178         f = fopen(fn, "re");
1179         if (!f) {
1180                 if (errno == ENOENT)
1181                         return 0;
1182
1183                 log_warning("Failed to open configuration file %s: %m", fn);
1184                 return -errno;
1185         }
1186
1187         r = config_parse(fn, f, sections, items, false, NULL);
1188         if (r < 0)
1189                 log_warning("Failed to parse configuration file: %s", strerror(-r));
1190
1191         fclose(f);
1192
1193         return r;
1194 }
1195
1196 int main(int argc, char *argv[]) {
1197         Manager *m = NULL;
1198         int r;
1199
1200         log_set_target(LOG_TARGET_AUTO);
1201         log_parse_environment();
1202         log_open();
1203
1204         if (argc != 1) {
1205                 log_error("This program takes no arguments.");
1206                 r = -EINVAL;
1207                 goto finish;
1208         }
1209
1210         umask(0022);
1211
1212         m = manager_new();
1213         if (!m) {
1214                 log_error("Out of memory");
1215                 r = -ENOMEM;
1216                 goto finish;
1217         }
1218
1219         manager_parse_config_file(m);
1220
1221         r = manager_startup(m);
1222         if (r < 0) {
1223                 log_error("Failed to fully start up daemon: %s", strerror(-r));
1224                 goto finish;
1225         }
1226
1227         r = manager_run(m);
1228
1229 finish:
1230         if (m)
1231                 manager_free(m);
1232
1233         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1234 }