chiark / gitweb /
journald: parse configuration 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 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         uid_t uid;
243         gid_t gid;
244         int r;
245
246         assert(m);
247         assert(name);
248
249         r = get_user_creds(&name, &uid, &gid, NULL);
250         if (r < 0)
251                 return r;
252
253         return manager_add_user(m, uid, gid, name, _user);
254 }
255
256 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
257         struct passwd *p;
258
259         assert(m);
260
261         errno = 0;
262         p = getpwuid(uid);
263         if (!p)
264                 return errno ? -errno : -ENOENT;
265
266         return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
267 }
268
269 int manager_process_seat_device(Manager *m, struct udev_device *d) {
270         Device *device;
271         int r;
272
273         assert(m);
274
275         if (streq_ptr(udev_device_get_action(d), "remove")) {
276
277                 device = hashmap_get(m->devices, udev_device_get_syspath(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_syspath(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         int k;
417
418         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
419         if (r < 0) {
420                 if (r == -ENOENT)
421                         return 0;
422
423                 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
424                 return r;
425         }
426
427         while ((k = cg_read_subgroup(d, &name)) > 0) {
428                 User *user;
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         if (r >= 0 && k < 0)
450                 r = k;
451
452         closedir(d);
453
454         return r;
455 }
456
457 static int manager_enumerate_linger_users(Manager *m) {
458         DIR *d;
459         struct dirent *de;
460         int r = 0;
461
462         d = opendir("/var/lib/systemd/linger");
463         if (!d) {
464                 if (errno == ENOENT)
465                         return 0;
466
467                 log_error("Failed to open /var/lib/systemd/linger/: %m");
468                 return -errno;
469         }
470
471         while ((de = readdir(d))) {
472                 int k;
473
474                 if (!dirent_is_file(de))
475                         continue;
476
477                 k = manager_add_user_by_name(m, de->d_name, NULL);
478                 if (k < 0) {
479                         log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
480                         r = k;
481                 }
482         }
483
484         closedir(d);
485
486         return r;
487 }
488
489 int manager_enumerate_users(Manager *m) {
490         DIR *d;
491         struct dirent *de;
492         int r, k;
493
494         assert(m);
495
496         /* First, enumerate user cgroups */
497         r = manager_enumerate_users_from_cgroup(m);
498
499         /* Second, add lingering users on top */
500         k = manager_enumerate_linger_users(m);
501         if (k < 0)
502                 r = k;
503
504         /* Third, read in user data stored on disk */
505         d = opendir("/run/systemd/users");
506         if (!d) {
507                 if (errno == ENOENT)
508                         return 0;
509
510                 log_error("Failed to open /run/systemd/users: %m");
511                 return -errno;
512         }
513
514         while ((de = readdir(d))) {
515                 uid_t uid;
516                 User *u;
517
518                 if (!dirent_is_file(de))
519                         continue;
520
521                 k = parse_uid(de->d_name, &uid);
522                 if (k < 0) {
523                         log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
524                         continue;
525                 }
526
527                 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
528                 if (!u) {
529                         unlinkat(dirfd(d), de->d_name, 0);
530                         continue;
531                 }
532
533                 k = user_load(u);
534                 if (k < 0)
535                         r = k;
536         }
537
538         closedir(d);
539
540         return r;
541 }
542
543 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
544         User *u;
545         Iterator i;
546         int r = 0;
547
548         HASHMAP_FOREACH(u, m->users, i) {
549                 DIR *d;
550                 char *name;
551                 int k;
552
553                 if (!u->cgroup_path)
554                         continue;
555
556                 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
557                 if (k < 0) {
558                         if (k == -ENOENT)
559                                 continue;
560
561                         log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
562                         r = k;
563                         continue;
564                 }
565
566                 while ((k = cg_read_subgroup(d, &name)) > 0) {
567                         Session *session;
568
569                         if (streq(name, "shared"))
570                                 continue;
571
572                         k = manager_add_session(m, u, name, &session);
573                         if (k < 0) {
574                                 free(name);
575                                 break;
576                         }
577
578                         session_add_to_gc_queue(session);
579
580                         if (!session->cgroup_path)
581                                 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
582                                         k = -ENOMEM;
583                                         free(name);
584                                         break;
585                                 }
586
587                         free(name);
588                 }
589
590                 closedir(d);
591
592                 if (k < 0)
593                         r = k;
594         }
595
596         return r;
597 }
598
599 int manager_enumerate_sessions(Manager *m) {
600         DIR *d;
601         struct dirent *de;
602         int r = 0;
603
604         assert(m);
605
606         /* First enumerate session cgroups */
607         r = manager_enumerate_sessions_from_cgroup(m);
608
609         /* Second, read in session data stored on disk */
610         d = opendir("/run/systemd/sessions");
611         if (!d) {
612                 if (errno == ENOENT)
613                         return 0;
614
615                 log_error("Failed to open /run/systemd/sessions: %m");
616                 return -errno;
617         }
618
619         while ((de = readdir(d))) {
620                 struct Session *s;
621                 int k;
622
623                 if (!dirent_is_file(de))
624                         continue;
625
626                 s = hashmap_get(m->sessions, de->d_name);
627                 if (!s) {
628                         unlinkat(dirfd(d), de->d_name, 0);
629                         continue;
630                 }
631
632                 k = session_load(s);
633                 if (k < 0)
634                         r = k;
635         }
636
637         closedir(d);
638
639         return r;
640 }
641
642 int manager_dispatch_seat_udev(Manager *m) {
643         struct udev_device *d;
644         int r;
645
646         assert(m);
647
648         d = udev_monitor_receive_device(m->udev_seat_monitor);
649         if (!d)
650                 return -ENOMEM;
651
652         r = manager_process_seat_device(m, d);
653         udev_device_unref(d);
654
655         return r;
656 }
657
658 int manager_dispatch_vcsa_udev(Manager *m) {
659         struct udev_device *d;
660         int r = 0;
661         const char *name;
662
663         assert(m);
664
665         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
666         if (!d)
667                 return -ENOMEM;
668
669         name = udev_device_get_sysname(d);
670
671         /* Whenever a VCSA device is removed try to reallocate our
672          * VTs, to make sure our auto VTs never go away. */
673
674         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
675                 r = seat_preallocate_vts(m->vtconsole);
676
677         udev_device_unref(d);
678
679         return r;
680 }
681
682 int manager_dispatch_console(Manager *m) {
683         assert(m);
684
685         if (m->vtconsole)
686                 seat_read_active_vt(m->vtconsole);
687
688         return 0;
689 }
690
691 static int vt_is_busy(int vtnr) {
692         struct vt_stat vt_stat;
693         int r = 0, fd;
694
695         assert(vtnr >= 1);
696
697         /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
698          * we'd open the latter we'd open the foreground tty which
699          * hence would be unconditionally busy. By opening /dev/tty1
700          * we avoid this. Since tty1 is special and needs to be an
701          * explicitly loaded getty or DM this is safe. */
702
703         fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
704         if (fd < 0)
705                 return -errno;
706
707         if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
708                 r = -errno;
709         else
710                 r = !!(vt_stat.v_state & (1 << vtnr));
711
712         close_nointr_nofail(fd);
713
714         return r;
715 }
716
717 int manager_spawn_autovt(Manager *m, int vtnr) {
718         int r;
719         DBusMessage *message = NULL, *reply = NULL;
720         char *name = NULL;
721         const char *mode = "fail";
722         DBusError error;
723
724         assert(m);
725         assert(vtnr >= 1);
726
727         dbus_error_init(&error);
728
729         if ((unsigned) vtnr > m->n_autovts)
730                 return 0;
731
732         r = vt_is_busy(vtnr);
733         if (r < 0)
734                 return r;
735         else if (r > 0)
736                 return -EBUSY;
737
738         message = dbus_message_new_method_call("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit");
739         if (!message) {
740                 log_error("Could not allocate message.");
741                 r = -ENOMEM;
742                 goto finish;
743         }
744
745         if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
746                 log_error("Could not allocate service name.");
747                 r = -ENOMEM;
748                 goto finish;
749         }
750
751         if (!dbus_message_append_args(message,
752                                       DBUS_TYPE_STRING, &name,
753                                       DBUS_TYPE_STRING, &mode,
754                                       DBUS_TYPE_INVALID)) {
755                 log_error("Could not attach target and flag information to message.");
756                 r = -ENOMEM;
757                 goto finish;
758         }
759
760         reply = dbus_connection_send_with_reply_and_block(m->bus, message, -1, &error);
761         if (!reply) {
762                 log_error("Failed to start unit: %s", bus_error_message(&error));
763                 goto finish;
764         }
765
766         r = 0;
767
768 finish:
769         free(name);
770
771         if (message)
772                 dbus_message_unref(message);
773
774         if (reply)
775                 dbus_message_unref(reply);
776
777         dbus_error_free(&error);
778
779         return r;
780 }
781
782 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
783         Session *s;
784         char *p;
785
786         assert(m);
787         assert(cgroup);
788
789         p = strdup(cgroup);
790         if (!p) {
791                 log_error("Out of memory.");
792                 return;
793         }
794
795         for (;;) {
796                 char *e;
797
798                 if (isempty(p) || streq(p, "/"))
799                         break;
800
801                 s = hashmap_get(m->cgroups, p);
802                 if (s)
803                         session_add_to_gc_queue(s);
804
805                 assert_se(e = strrchr(p, '/'));
806                 *e = 0;
807         }
808
809         free(p);
810 }
811
812 static void manager_pipe_notify_eof(Manager *m, int fd) {
813         Session *s;
814
815         assert_se(m);
816         assert_se(fd >= 0);
817
818         assert_se(s = hashmap_get(m->fifo_fds, INT_TO_PTR(fd + 1)));
819         assert(s->fifo_fd == fd);
820         session_remove_fifo(s);
821
822         session_stop(s);
823 }
824
825 static int manager_connect_bus(Manager *m) {
826         DBusError error;
827         int r;
828         struct epoll_event ev;
829
830         assert(m);
831         assert(!m->bus);
832         assert(m->bus_fd < 0);
833
834         dbus_error_init(&error);
835
836         m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
837         if (!m->bus) {
838                 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
839                 r = -ECONNREFUSED;
840                 goto fail;
841         }
842
843         if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
844             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
845             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
846             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
847             !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
848                 log_error("Not enough memory");
849                 r = -ENOMEM;
850                 goto fail;
851         }
852
853         dbus_bus_add_match(m->bus,
854                            "type='signal',"
855                            "interface='org.freedesktop.systemd1.Agent',"
856                            "member='Released',"
857                            "path='/org/freedesktop/systemd1/agent'",
858                            &error);
859
860         if (dbus_error_is_set(&error)) {
861                 log_error("Failed to register match: %s", bus_error_message(&error));
862                 r = -EIO;
863                 goto fail;
864         }
865
866         r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
867         if (dbus_error_is_set(&error)) {
868                 log_error("Failed to register name on bus: %s", bus_error_message(&error));
869                 r = -EIO;
870                 goto fail;
871         }
872
873         if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {
874                 log_error("Failed to acquire name.");
875                 r = -EEXIST;
876                 goto fail;
877         }
878
879         m->bus_fd = bus_loop_open(m->bus);
880         if (m->bus_fd < 0) {
881                 r = m->bus_fd;
882                 goto fail;
883         }
884
885         zero(ev);
886         ev.events = EPOLLIN;
887         ev.data.u32 = FD_BUS;
888
889         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
890                 goto fail;
891
892         return 0;
893
894 fail:
895         dbus_error_free(&error);
896
897         return r;
898 }
899
900 static int manager_connect_console(Manager *m) {
901         struct epoll_event ev;
902
903         assert(m);
904         assert(m->console_active_fd < 0);
905
906         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
907         if (m->console_active_fd < 0) {
908
909                 /* On certain architectures (S390 and Xen), /dev/tty0
910                    does not exist, so don't fail if we can't open it.*/
911                 if (errno == ENOENT)
912                         return 0;
913
914                 log_error("Failed to open /sys/class/tty/tty0/active: %m");
915                 return -errno;
916         }
917
918         zero(ev);
919         ev.events = 0;
920         ev.data.u32 = FD_CONSOLE;
921
922         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
923                 return -errno;
924
925         return 0;
926 }
927
928 static int manager_connect_udev(Manager *m) {
929         struct epoll_event ev;
930         int r;
931
932         assert(m);
933         assert(!m->udev_seat_monitor);
934         assert(!m->udev_vcsa_monitor);
935
936         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
937         if (!m->udev_seat_monitor)
938                 return -ENOMEM;
939
940         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
941         if (r < 0)
942                 return r;
943
944         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
945         if (r < 0)
946                 return r;
947
948         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
949         if (r < 0)
950                 return r;
951
952         m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
953
954         zero(ev);
955         ev.events = EPOLLIN;
956         ev.data.u32 = FD_SEAT_UDEV;
957
958         /* Don't bother watching VCSA devices, if nobody cares */
959         if (m->n_autovts <= 0 || m->console_active_fd < 0)
960                 return 0;
961
962         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
963                 return -errno;
964
965         m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
966         if (!m->udev_vcsa_monitor)
967                 return -ENOMEM;
968
969         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
970         if (r < 0)
971                 return r;
972
973         r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
974         if (r < 0)
975                 return r;
976
977         m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
978
979         zero(ev);
980         ev.events = EPOLLIN;
981         ev.data.u32 = FD_VCSA_UDEV;
982
983         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
984                 return -errno;
985
986         return 0;
987 }
988
989 void manager_gc(Manager *m, bool drop_not_started) {
990         Seat *seat;
991         Session *session;
992         User *user;
993
994         assert(m);
995
996         while ((seat = m->seat_gc_queue)) {
997                 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
998                 seat->in_gc_queue = false;
999
1000                 if (seat_check_gc(seat, drop_not_started) == 0) {
1001                         seat_stop(seat);
1002                         seat_free(seat);
1003                 }
1004         }
1005
1006         while ((session = m->session_gc_queue)) {
1007                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1008                 session->in_gc_queue = false;
1009
1010                 if (session_check_gc(session, drop_not_started) == 0) {
1011                         session_stop(session);
1012                         session_free(session);
1013                 }
1014         }
1015
1016         while ((user = m->user_gc_queue)) {
1017                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1018                 user->in_gc_queue = false;
1019
1020                 if (user_check_gc(user, drop_not_started) == 0) {
1021                         user_stop(user);
1022                         user_free(user);
1023                 }
1024         }
1025 }
1026
1027 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1028         Session *s;
1029         bool idle_hint = true;
1030         dual_timestamp ts = { 0, 0 };
1031         Iterator i;
1032
1033         assert(m);
1034
1035         HASHMAP_FOREACH(s, m->sessions, i) {
1036                 dual_timestamp k;
1037                 int ih;
1038
1039                 ih = session_get_idle_hint(s, &k);
1040                 if (ih < 0)
1041                         return ih;
1042
1043                 if (!ih) {
1044                         if (!idle_hint) {
1045                                 if (k.monotonic < ts.monotonic)
1046                                         ts = k;
1047                         } else {
1048                                 idle_hint = false;
1049                                 ts = k;
1050                         }
1051                 } else if (idle_hint) {
1052
1053                         if (k.monotonic > ts.monotonic)
1054                                 ts = k;
1055                 }
1056         }
1057
1058         if (t)
1059                 *t = ts;
1060
1061         return idle_hint;
1062 }
1063
1064 int manager_startup(Manager *m) {
1065         int r;
1066         Seat *seat;
1067         Session *session;
1068         User *user;
1069         Iterator i;
1070
1071         assert(m);
1072         assert(m->epoll_fd <= 0);
1073
1074         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1075         if (m->epoll_fd < 0)
1076                 return -errno;
1077
1078         /* Connect to console */
1079         r = manager_connect_console(m);
1080         if (r < 0)
1081                 return r;
1082
1083         /* Connect to udev */
1084         r = manager_connect_udev(m);
1085         if (r < 0)
1086                 return r;
1087
1088         /* Connect to the bus */
1089         r = manager_connect_bus(m);
1090         if (r < 0)
1091                 return r;
1092
1093         /* Instantiate magic seat 0 */
1094         r = manager_add_seat(m, "seat0", &m->vtconsole);
1095         if (r < 0)
1096                 return r;
1097
1098         /* Deserialize state */
1099         manager_enumerate_devices(m);
1100         manager_enumerate_seats(m);
1101         manager_enumerate_users(m);
1102         manager_enumerate_sessions(m);
1103
1104         /* Remove stale objects before we start them */
1105         manager_gc(m, false);
1106
1107         /* And start everything */
1108         HASHMAP_FOREACH(seat, m->seats, i)
1109                 seat_start(seat);
1110
1111         HASHMAP_FOREACH(user, m->users, i)
1112                 user_start(user);
1113
1114         HASHMAP_FOREACH(session, m->sessions, i)
1115                 session_start(session);
1116
1117         return 0;
1118 }
1119
1120 int manager_run(Manager *m) {
1121         assert(m);
1122
1123         for (;;) {
1124                 struct epoll_event event;
1125                 int n;
1126
1127                 manager_gc(m, true);
1128
1129                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1130                         continue;
1131
1132                 manager_gc(m, true);
1133
1134                 n = epoll_wait(m->epoll_fd, &event, 1, -1);
1135                 if (n < 0) {
1136                         if (errno == EINTR || errno == EAGAIN)
1137                                 continue;
1138
1139                         log_error("epoll() failed: %m");
1140                         return -errno;
1141                 }
1142
1143                 switch (event.data.u32) {
1144
1145                 case FD_SEAT_UDEV:
1146                         manager_dispatch_seat_udev(m);
1147                         break;
1148
1149                 case FD_VCSA_UDEV:
1150                         manager_dispatch_vcsa_udev(m);
1151                         break;
1152
1153                 case FD_CONSOLE:
1154                         manager_dispatch_console(m);
1155                         break;
1156
1157                 case FD_BUS:
1158                         bus_loop_dispatch(m->bus_fd);
1159                         break;
1160
1161                 default:
1162                         if (event.data.u32 >= FD_FIFO_BASE)
1163                                 manager_pipe_notify_eof(m, event.data.u32 - FD_FIFO_BASE);
1164                 }
1165         }
1166
1167         return 0;
1168 }
1169
1170 static int manager_parse_config_file(Manager *m) {
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, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
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         umask(0022);
1205
1206         if (argc != 1) {
1207                 log_error("This program takes no arguments.");
1208                 r = -EINVAL;
1209                 goto finish;
1210         }
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         log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1228
1229         sd_notify(false,
1230                   "READY=1\n"
1231                   "STATUS=Processing requests...");
1232
1233         r = manager_run(m);
1234
1235         log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1236
1237 finish:
1238         sd_notify(false,
1239                   "STATUS=Shutting down...");
1240
1241         if (m)
1242                 manager_free(m);
1243
1244         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1245 }