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