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