chiark / gitweb /
logind: make VT reservation logic compatible with containers
[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->udev_button_fd = -1;
52         m->epoll_fd = -1;
53         m->reserve_vt_fd = -1;
54
55         m->n_autovts = 6;
56         m->reserve_vt = 6;
57         m->inhibit_delay_max = 5 * USEC_PER_SEC;
58         m->handle_power_key = HANDLE_NO_SESSION;
59         m->handle_sleep_key = HANDLE_TTY_SESSION;
60         m->handle_lid_switch = HANDLE_OFF;
61
62         m->devices = hashmap_new(string_hash_func, string_compare_func);
63         m->seats = hashmap_new(string_hash_func, string_compare_func);
64         m->sessions = hashmap_new(string_hash_func, string_compare_func);
65         m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
66         m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
67         m->buttons = hashmap_new(string_hash_func, string_compare_func);
68
69         m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
70         m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
71
72         m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
73         m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
74         m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
75
76         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
77             !m->user_cgroups || !m->session_cgroups ||
78             !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
79                 manager_free(m);
80                 return NULL;
81         }
82
83         m->reset_controllers = strv_new("cpu", NULL);
84         m->kill_exclude_users = strv_new("root", NULL);
85         if (!m->reset_controllers || !m->kill_exclude_users) {
86                 manager_free(m);
87                 return NULL;
88         }
89
90         m->udev = udev_new();
91         if (!m->udev) {
92                 manager_free(m);
93                 return NULL;
94         }
95
96         if (cg_get_user_path(&m->cgroup_path) < 0) {
97                 manager_free(m);
98                 return NULL;
99         }
100
101         return m;
102 }
103
104 void manager_free(Manager *m) {
105         Session *session;
106         User *u;
107         Device *d;
108         Seat *s;
109         Inhibitor *i;
110         Button *b;
111
112         assert(m);
113
114         while ((session = hashmap_first(m->sessions)))
115                 session_free(session);
116
117         while ((u = hashmap_first(m->users)))
118                 user_free(u);
119
120         while ((d = hashmap_first(m->devices)))
121                 device_free(d);
122
123         while ((s = hashmap_first(m->seats)))
124                 seat_free(s);
125
126         while ((i = hashmap_first(m->inhibitors)))
127                 inhibitor_free(i);
128
129         while ((b = hashmap_first(m->buttons)))
130                 button_free(b);
131
132         hashmap_free(m->devices);
133         hashmap_free(m->seats);
134         hashmap_free(m->sessions);
135         hashmap_free(m->users);
136         hashmap_free(m->inhibitors);
137         hashmap_free(m->buttons);
138
139         hashmap_free(m->user_cgroups);
140         hashmap_free(m->session_cgroups);
141
142         hashmap_free(m->session_fds);
143         hashmap_free(m->inhibitor_fds);
144         hashmap_free(m->button_fds);
145
146         if (m->console_active_fd >= 0)
147                 close_nointr_nofail(m->console_active_fd);
148
149         if (m->udev_seat_monitor)
150                 udev_monitor_unref(m->udev_seat_monitor);
151         if (m->udev_vcsa_monitor)
152                 udev_monitor_unref(m->udev_vcsa_monitor);
153         if (m->udev_button_monitor)
154                 udev_monitor_unref(m->udev_button_monitor);
155
156         if (m->udev)
157                 udev_unref(m->udev);
158
159         if (m->bus) {
160                 dbus_connection_flush(m->bus);
161                 dbus_connection_close(m->bus);
162                 dbus_connection_unref(m->bus);
163         }
164
165         if (m->bus_fd >= 0)
166                 close_nointr_nofail(m->bus_fd);
167
168         if (m->epoll_fd >= 0)
169                 close_nointr_nofail(m->epoll_fd);
170
171         if (m->reserve_vt_fd >= 0)
172                 close_nointr_nofail(m->reserve_vt_fd);
173
174         strv_free(m->controllers);
175         strv_free(m->reset_controllers);
176         strv_free(m->kill_only_users);
177         strv_free(m->kill_exclude_users);
178
179         free(m->cgroup_path);
180         free(m);
181 }
182
183 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
184         Device *d;
185
186         assert(m);
187         assert(sysfs);
188
189         d = hashmap_get(m->devices, sysfs);
190         if (d) {
191                 if (_device)
192                         *_device = d;
193
194                 return 0;
195         }
196
197         d = device_new(m, sysfs);
198         if (!d)
199                 return -ENOMEM;
200
201         if (_device)
202                 *_device = d;
203
204         return 0;
205 }
206
207 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
208         Seat *s;
209
210         assert(m);
211         assert(id);
212
213         s = hashmap_get(m->seats, id);
214         if (s) {
215                 if (_seat)
216                         *_seat = s;
217
218                 return 0;
219         }
220
221         s = seat_new(m, id);
222         if (!s)
223                 return -ENOMEM;
224
225         if (_seat)
226                 *_seat = s;
227
228         return 0;
229 }
230
231 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
232         Session *s;
233
234         assert(m);
235         assert(id);
236
237         s = hashmap_get(m->sessions, id);
238         if (s) {
239                 if (_session)
240                         *_session = s;
241
242                 return 0;
243         }
244
245         s = session_new(m, u, id);
246         if (!s)
247                 return -ENOMEM;
248
249         if (_session)
250                 *_session = s;
251
252         return 0;
253 }
254
255 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
256         User *u;
257
258         assert(m);
259         assert(name);
260
261         u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
262         if (u) {
263                 if (_user)
264                         *_user = u;
265
266                 return 0;
267         }
268
269         u = user_new(m, uid, gid, name);
270         if (!u)
271                 return -ENOMEM;
272
273         if (_user)
274                 *_user = u;
275
276         return 0;
277 }
278
279 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
280         uid_t uid;
281         gid_t gid;
282         int r;
283
284         assert(m);
285         assert(name);
286
287         r = get_user_creds(&name, &uid, &gid, NULL, NULL);
288         if (r < 0)
289                 return r;
290
291         return manager_add_user(m, uid, gid, name, _user);
292 }
293
294 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
295         struct passwd *p;
296
297         assert(m);
298
299         errno = 0;
300         p = getpwuid(uid);
301         if (!p)
302                 return errno ? -errno : -ENOENT;
303
304         return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
305 }
306
307 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
308         Inhibitor *i;
309
310         assert(m);
311         assert(id);
312
313         i = hashmap_get(m->inhibitors, id);
314         if (i) {
315                 if (_inhibitor)
316                         *_inhibitor = i;
317
318                 return 0;
319         }
320
321         i = inhibitor_new(m, id);
322         if (!i)
323                 return -ENOMEM;
324
325         if (_inhibitor)
326                 *_inhibitor = i;
327
328         return 0;
329 }
330
331 int manager_add_button(Manager *m, const char *name, Button **_button) {
332         Button *b;
333
334         assert(m);
335         assert(name);
336
337         b = hashmap_get(m->buttons, name);
338         if (b) {
339                 if (_button)
340                         *_button = b;
341
342                 return 0;
343         }
344
345         b = button_new(m, name);
346         if (!b)
347                 return -ENOMEM;
348
349         if (_button)
350                 *_button = b;
351
352         return 0;
353 }
354
355 int manager_process_seat_device(Manager *m, struct udev_device *d) {
356         Device *device;
357         int r;
358
359         assert(m);
360
361         if (streq_ptr(udev_device_get_action(d), "remove")) {
362
363                 device = hashmap_get(m->devices, udev_device_get_syspath(d));
364                 if (!device)
365                         return 0;
366
367                 seat_add_to_gc_queue(device->seat);
368                 device_free(device);
369
370         } else {
371                 const char *sn;
372                 Seat *seat;
373
374                 sn = udev_device_get_property_value(d, "ID_SEAT");
375                 if (isempty(sn))
376                         sn = "seat0";
377
378                 if (!seat_name_is_valid(sn)) {
379                         log_warning("Device with invalid seat name %s found, ignoring.", sn);
380                         return 0;
381                 }
382
383                 r = manager_add_device(m, udev_device_get_syspath(d), &device);
384                 if (r < 0)
385                         return r;
386
387                 r = manager_add_seat(m, sn, &seat);
388                 if (r < 0) {
389                         if (!device->seat)
390                                 device_free(device);
391
392                         return r;
393                 }
394
395                 device_attach(device, seat);
396                 seat_start(seat);
397         }
398
399         return 0;
400 }
401
402 int manager_process_button_device(Manager *m, struct udev_device *d) {
403         Button *b;
404
405         int r;
406
407         assert(m);
408
409         if (streq_ptr(udev_device_get_action(d), "remove")) {
410
411                 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
412                 if (!b)
413                         return 0;
414
415                 button_free(b);
416
417         } else {
418                 const char *sn;
419
420                 r = manager_add_button(m, udev_device_get_sysname(d), &b);
421                 if (r < 0)
422                         return r;
423
424                 sn = udev_device_get_property_value(d, "ID_SEAT");
425                 if (isempty(sn))
426                         sn = "seat0";
427
428                 button_set_seat(b, sn);
429                 button_open(b);
430         }
431
432         return 0;
433 }
434
435 int manager_enumerate_devices(Manager *m) {
436         struct udev_list_entry *item = NULL, *first = NULL;
437         struct udev_enumerate *e;
438         int r;
439
440         assert(m);
441
442         /* Loads devices from udev and creates seats for them as
443          * necessary */
444
445         e = udev_enumerate_new(m->udev);
446         if (!e) {
447                 r = -ENOMEM;
448                 goto finish;
449         }
450
451         r = udev_enumerate_add_match_subsystem(e, "graphics");
452         if (r < 0)
453                 goto finish;
454
455         r = udev_enumerate_add_match_tag(e, "seat");
456         if (r < 0)
457                 goto finish;
458
459         r = udev_enumerate_scan_devices(e);
460         if (r < 0)
461                 goto finish;
462
463         first = udev_enumerate_get_list_entry(e);
464         udev_list_entry_foreach(item, first) {
465                 struct udev_device *d;
466                 int k;
467
468                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
469                 if (!d) {
470                         r = -ENOMEM;
471                         goto finish;
472                 }
473
474                 k = manager_process_seat_device(m, d);
475                 udev_device_unref(d);
476
477                 if (k < 0)
478                         r = k;
479         }
480
481 finish:
482         if (e)
483                 udev_enumerate_unref(e);
484
485         return r;
486 }
487
488 int manager_enumerate_buttons(Manager *m) {
489         struct udev_list_entry *item = NULL, *first = NULL;
490         struct udev_enumerate *e;
491         int r;
492
493         assert(m);
494
495         /* Loads buttons from udev */
496
497         if (m->handle_power_key == HANDLE_OFF &&
498             m->handle_sleep_key == HANDLE_OFF &&
499             m->handle_lid_switch == HANDLE_OFF)
500                 return 0;
501
502         e = udev_enumerate_new(m->udev);
503         if (!e) {
504                 r = -ENOMEM;
505                 goto finish;
506         }
507
508         r = udev_enumerate_add_match_subsystem(e, "input");
509         if (r < 0)
510                 goto finish;
511
512         r = udev_enumerate_add_match_tag(e, "power-switch");
513         if (r < 0)
514                 goto finish;
515
516         r = udev_enumerate_scan_devices(e);
517         if (r < 0)
518                 goto finish;
519
520         first = udev_enumerate_get_list_entry(e);
521         udev_list_entry_foreach(item, first) {
522                 struct udev_device *d;
523                 int k;
524
525                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
526                 if (!d) {
527                         r = -ENOMEM;
528                         goto finish;
529                 }
530
531                 k = manager_process_button_device(m, d);
532                 udev_device_unref(d);
533
534                 if (k < 0)
535                         r = k;
536         }
537
538 finish:
539         if (e)
540                 udev_enumerate_unref(e);
541
542         return r;
543 }
544
545 int manager_enumerate_seats(Manager *m) {
546         DIR *d;
547         struct dirent *de;
548         int r = 0;
549
550         assert(m);
551
552         /* This loads data about seats stored on disk, but does not
553          * actually create any seats. Removes data of seats that no
554          * longer exist. */
555
556         d = opendir("/run/systemd/seats");
557         if (!d) {
558                 if (errno == ENOENT)
559                         return 0;
560
561                 log_error("Failed to open /run/systemd/seats: %m");
562                 return -errno;
563         }
564
565         while ((de = readdir(d))) {
566                 Seat *s;
567                 int k;
568
569                 if (!dirent_is_file(de))
570                         continue;
571
572                 s = hashmap_get(m->seats, de->d_name);
573                 if (!s) {
574                         unlinkat(dirfd(d), de->d_name, 0);
575                         continue;
576                 }
577
578                 k = seat_load(s);
579                 if (k < 0)
580                         r = k;
581         }
582
583         closedir(d);
584
585         return r;
586 }
587
588 static int manager_enumerate_users_from_cgroup(Manager *m) {
589         int r = 0, k;
590         char *name;
591         DIR *d;
592
593         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
594         if (r < 0) {
595                 if (r == -ENOENT)
596                         return 0;
597
598                 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
599                 return r;
600         }
601
602         while ((k = cg_read_subgroup(d, &name)) > 0) {
603                 User *user;
604
605                 k = manager_add_user_by_name(m, name, &user);
606                 if (k < 0) {
607                         free(name);
608                         r = k;
609                         continue;
610                 }
611
612                 user_add_to_gc_queue(user);
613
614                 if (!user->cgroup_path)
615                         if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
616                                 r = -ENOMEM;
617                                 free(name);
618                                 break;
619                         }
620
621                 free(name);
622         }
623
624         if (r >= 0 && k < 0)
625                 r = k;
626
627         closedir(d);
628
629         return r;
630 }
631
632 static int manager_enumerate_linger_users(Manager *m) {
633         DIR *d;
634         struct dirent *de;
635         int r = 0;
636
637         d = opendir("/var/lib/systemd/linger");
638         if (!d) {
639                 if (errno == ENOENT)
640                         return 0;
641
642                 log_error("Failed to open /var/lib/systemd/linger/: %m");
643                 return -errno;
644         }
645
646         while ((de = readdir(d))) {
647                 int k;
648
649                 if (!dirent_is_file(de))
650                         continue;
651
652                 k = manager_add_user_by_name(m, de->d_name, NULL);
653                 if (k < 0) {
654                         log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
655                         r = k;
656                 }
657         }
658
659         closedir(d);
660
661         return r;
662 }
663
664 int manager_enumerate_users(Manager *m) {
665         DIR *d;
666         struct dirent *de;
667         int r, k;
668
669         assert(m);
670
671         /* First, enumerate user cgroups */
672         r = manager_enumerate_users_from_cgroup(m);
673
674         /* Second, add lingering users on top */
675         k = manager_enumerate_linger_users(m);
676         if (k < 0)
677                 r = k;
678
679         /* Third, read in user data stored on disk */
680         d = opendir("/run/systemd/users");
681         if (!d) {
682                 if (errno == ENOENT)
683                         return 0;
684
685                 log_error("Failed to open /run/systemd/users: %m");
686                 return -errno;
687         }
688
689         while ((de = readdir(d))) {
690                 uid_t uid;
691                 User *u;
692
693                 if (!dirent_is_file(de))
694                         continue;
695
696                 k = parse_uid(de->d_name, &uid);
697                 if (k < 0) {
698                         log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
699                         continue;
700                 }
701
702                 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
703                 if (!u) {
704                         unlinkat(dirfd(d), de->d_name, 0);
705                         continue;
706                 }
707
708                 k = user_load(u);
709                 if (k < 0)
710                         r = k;
711         }
712
713         closedir(d);
714
715         return r;
716 }
717
718 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
719         User *u;
720         Iterator i;
721         int r = 0;
722
723         HASHMAP_FOREACH(u, m->users, i) {
724                 DIR *d;
725                 char *name;
726                 int k;
727
728                 if (!u->cgroup_path)
729                         continue;
730
731                 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
732                 if (k < 0) {
733                         if (k == -ENOENT)
734                                 continue;
735
736                         log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
737                         r = k;
738                         continue;
739                 }
740
741                 while ((k = cg_read_subgroup(d, &name)) > 0) {
742                         Session *session;
743
744                         if (streq(name, "shared"))
745                                 continue;
746
747                         k = manager_add_session(m, u, name, &session);
748                         if (k < 0) {
749                                 free(name);
750                                 break;
751                         }
752
753                         session_add_to_gc_queue(session);
754
755                         if (!session->cgroup_path)
756                                 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
757                                         k = -ENOMEM;
758                                         free(name);
759                                         break;
760                                 }
761
762                         free(name);
763                 }
764
765                 closedir(d);
766
767                 if (k < 0)
768                         r = k;
769         }
770
771         return r;
772 }
773
774 int manager_enumerate_sessions(Manager *m) {
775         DIR *d;
776         struct dirent *de;
777         int r = 0;
778
779         assert(m);
780
781         /* First enumerate session cgroups */
782         r = manager_enumerate_sessions_from_cgroup(m);
783
784         /* Second, read in session data stored on disk */
785         d = opendir("/run/systemd/sessions");
786         if (!d) {
787                 if (errno == ENOENT)
788                         return 0;
789
790                 log_error("Failed to open /run/systemd/sessions: %m");
791                 return -errno;
792         }
793
794         while ((de = readdir(d))) {
795                 struct Session *s;
796                 int k;
797
798                 if (!dirent_is_file(de))
799                         continue;
800
801                 s = hashmap_get(m->sessions, de->d_name);
802                 if (!s) {
803                         unlinkat(dirfd(d), de->d_name, 0);
804                         continue;
805                 }
806
807                 k = session_load(s);
808                 if (k < 0)
809                         r = k;
810         }
811
812         closedir(d);
813
814         return r;
815 }
816
817 int manager_enumerate_inhibitors(Manager *m) {
818         DIR *d;
819         struct dirent *de;
820         int r = 0;
821
822         assert(m);
823
824         d = opendir("/run/systemd/inhibit");
825         if (!d) {
826                 if (errno == ENOENT)
827                         return 0;
828
829                 log_error("Failed to open /run/systemd/inhibit: %m");
830                 return -errno;
831         }
832
833         while ((de = readdir(d))) {
834                 int k;
835                 Inhibitor *i;
836
837                 if (!dirent_is_file(de))
838                         continue;
839
840                 k = manager_add_inhibitor(m, de->d_name, &i);
841                 if (k < 0) {
842                         log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
843                         r = k;
844                         continue;
845                 }
846
847                 k = inhibitor_load(i);
848                 if (k < 0)
849                         r = k;
850         }
851
852         closedir(d);
853
854         return r;
855 }
856
857 int manager_dispatch_seat_udev(Manager *m) {
858         struct udev_device *d;
859         int r;
860
861         assert(m);
862
863         d = udev_monitor_receive_device(m->udev_seat_monitor);
864         if (!d)
865                 return -ENOMEM;
866
867         r = manager_process_seat_device(m, d);
868         udev_device_unref(d);
869
870         return r;
871 }
872
873 int manager_dispatch_vcsa_udev(Manager *m) {
874         struct udev_device *d;
875         int r = 0;
876         const char *name;
877
878         assert(m);
879
880         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
881         if (!d)
882                 return -ENOMEM;
883
884         name = udev_device_get_sysname(d);
885
886         /* Whenever a VCSA device is removed try to reallocate our
887          * VTs, to make sure our auto VTs never go away. */
888
889         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
890                 r = seat_preallocate_vts(m->vtconsole);
891
892         udev_device_unref(d);
893
894         return r;
895 }
896
897 int manager_dispatch_button_udev(Manager *m) {
898         struct udev_device *d;
899         int r;
900
901         assert(m);
902
903         d = udev_monitor_receive_device(m->udev_button_monitor);
904         if (!d)
905                 return -ENOMEM;
906
907         r = manager_process_button_device(m, d);
908         udev_device_unref(d);
909
910         return r;
911 }
912
913 int manager_dispatch_console(Manager *m) {
914         assert(m);
915
916         if (m->vtconsole)
917                 seat_read_active_vt(m->vtconsole);
918
919         return 0;
920 }
921
922 static int vt_is_busy(int vtnr) {
923         struct vt_stat vt_stat;
924         int r = 0, fd;
925
926         assert(vtnr >= 1);
927
928         /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
929          * we'd open the latter we'd open the foreground tty which
930          * hence would be unconditionally busy. By opening /dev/tty1
931          * we avoid this. Since tty1 is special and needs to be an
932          * explicitly loaded getty or DM this is safe. */
933
934         fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
935         if (fd < 0)
936                 return -errno;
937
938         if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
939                 r = -errno;
940         else
941                 r = !!(vt_stat.v_state & (1 << vtnr));
942
943         close_nointr_nofail(fd);
944
945         return r;
946 }
947
948 int manager_spawn_autovt(Manager *m, int vtnr) {
949         int r;
950         char *name = NULL;
951         const char *mode = "fail";
952
953         assert(m);
954         assert(vtnr >= 1);
955
956         if ((unsigned) vtnr > m->n_autovts &&
957             (unsigned) vtnr != m->reserve_vt)
958                 return 0;
959
960         if ((unsigned) vtnr != m->reserve_vt) {
961                 /* If this is the reserved TTY, we'll start the getty
962                  * on it in any case, but otherwise only if it is not
963                  * busy. */
964
965                 r = vt_is_busy(vtnr);
966                 if (r < 0)
967                         return r;
968                 else if (r > 0)
969                         return -EBUSY;
970         }
971
972         if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
973                 log_error("Could not allocate service name.");
974                 r = -ENOMEM;
975                 goto finish;
976         }
977
978         r = bus_method_call_with_reply (
979                         m->bus,
980                         "org.freedesktop.systemd1",
981                         "/org/freedesktop/systemd1",
982                         "org.freedesktop.systemd1.Manager",
983                         "StartUnit",
984                         NULL,
985                         NULL,
986                         DBUS_TYPE_STRING, &name,
987                         DBUS_TYPE_STRING, &mode,
988                         DBUS_TYPE_INVALID);
989
990 finish:
991         free(name);
992
993         return r;
994 }
995
996 static int manager_reserve_vt(Manager *m) {
997         _cleanup_free_ char *p = NULL;
998
999         assert(m);
1000
1001         if (m->reserve_vt <= 0)
1002                 return 0;
1003
1004         if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1005                 return log_oom();
1006
1007         m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1008         if (m->reserve_vt_fd < 0) {
1009
1010                 /* Don't complain on VT-less systems */
1011                 if (errno != ENOENT)
1012                         log_warning("Failed to pin reserved VT: %m");
1013                 return -errno;
1014         }
1015
1016         return 0;
1017 }
1018
1019 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1020         Session *s;
1021         char *p;
1022
1023         assert(m);
1024         assert(cgroup);
1025         assert(session);
1026
1027         s = hashmap_get(m->session_cgroups, cgroup);
1028         if (s) {
1029                 *session = s;
1030                 return 1;
1031         }
1032
1033         p = strdup(cgroup);
1034         if (!p)
1035                 return log_oom();
1036
1037         for (;;) {
1038                 char *e;
1039
1040                 e = strrchr(p, '/');
1041                 if (!e || e == p) {
1042                         free(p);
1043                         *session = NULL;
1044                         return 0;
1045                 }
1046
1047                 *e = 0;
1048
1049                 s = hashmap_get(m->session_cgroups, p);
1050                 if (s) {
1051                         free(p);
1052                         *session = s;
1053                         return 1;
1054                 }
1055         }
1056 }
1057
1058 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1059         User *u;
1060         char *p;
1061
1062         assert(m);
1063         assert(cgroup);
1064         assert(user);
1065
1066         u = hashmap_get(m->user_cgroups, cgroup);
1067         if (u) {
1068                 *user = u;
1069                 return 1;
1070         }
1071
1072         p = strdup(cgroup);
1073         if (!p)
1074                 return log_oom();
1075
1076         for (;;) {
1077                 char *e;
1078
1079                 e = strrchr(p, '/');
1080                 if (!e || e == p) {
1081                         free(p);
1082                         *user = NULL;
1083                         return 0;
1084                 }
1085
1086                 *e = 0;
1087
1088                 u = hashmap_get(m->user_cgroups, p);
1089                 if (u) {
1090                         free(p);
1091                         *user = u;
1092                         return 1;
1093                 }
1094         }
1095 }
1096
1097 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1098         char *p;
1099         int r;
1100
1101         assert(m);
1102         assert(pid >= 1);
1103         assert(session);
1104
1105         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1106         if (r < 0)
1107                 return r;
1108
1109         r = manager_get_session_by_cgroup(m, p, session);
1110         free(p);
1111
1112         return r;
1113 }
1114
1115 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1116         Session *s;
1117         User *u;
1118         int r;
1119
1120         r = manager_get_session_by_cgroup(m, cgroup, &s);
1121         if (r > 0)
1122                 session_add_to_gc_queue(s);
1123
1124         r = manager_get_user_by_cgroup(m, cgroup, &u);
1125         if (r > 0)
1126                 user_add_to_gc_queue(u);
1127 }
1128
1129 static void manager_dispatch_other(Manager *m, int fd) {
1130         Session *s;
1131         Inhibitor *i;
1132         Button *b;
1133
1134         assert_se(m);
1135         assert_se(fd >= 0);
1136
1137         s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1138         if (s) {
1139                 assert(s->fifo_fd == fd);
1140                 session_remove_fifo(s);
1141                 session_stop(s);
1142                 return;
1143         }
1144
1145         i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1146         if (i) {
1147                 assert(i->fifo_fd == fd);
1148                 inhibitor_stop(i);
1149                 inhibitor_free(i);
1150                 return;
1151         }
1152
1153         b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1154         if (b) {
1155                 assert(b->fd == fd);
1156                 button_process(b);
1157                 return;
1158         }
1159
1160         assert_not_reached("Got event for unknown fd");
1161 }
1162
1163 static int manager_connect_bus(Manager *m) {
1164         DBusError error;
1165         int r;
1166         struct epoll_event ev;
1167
1168         assert(m);
1169         assert(!m->bus);
1170         assert(m->bus_fd < 0);
1171
1172         dbus_error_init(&error);
1173
1174         m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1175         if (!m->bus) {
1176                 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1177                 r = -ECONNREFUSED;
1178                 goto fail;
1179         }
1180
1181         if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1182             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1183             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1184             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1185             !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1186                 r = log_oom();
1187                 goto fail;
1188         }
1189
1190         dbus_bus_add_match(m->bus,
1191                            "type='signal',"
1192                            "interface='org.freedesktop.systemd1.Agent',"
1193                            "member='Released',"
1194                            "path='/org/freedesktop/systemd1/agent'",
1195                            &error);
1196
1197         if (dbus_error_is_set(&error)) {
1198                 log_error("Failed to register match: %s", bus_error_message(&error));
1199                 r = -EIO;
1200                 goto fail;
1201         }
1202
1203         r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1204         if (dbus_error_is_set(&error)) {
1205                 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1206                 r = -EIO;
1207                 goto fail;
1208         }
1209
1210         if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {
1211                 log_error("Failed to acquire name.");
1212                 r = -EEXIST;
1213                 goto fail;
1214         }
1215
1216         m->bus_fd = bus_loop_open(m->bus);
1217         if (m->bus_fd < 0) {
1218                 r = m->bus_fd;
1219                 goto fail;
1220         }
1221
1222         zero(ev);
1223         ev.events = EPOLLIN;
1224         ev.data.u32 = FD_BUS;
1225
1226         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1227                 goto fail;
1228
1229         return 0;
1230
1231 fail:
1232         dbus_error_free(&error);
1233
1234         return r;
1235 }
1236
1237 static int manager_connect_console(Manager *m) {
1238         struct epoll_event ev;
1239
1240         assert(m);
1241         assert(m->console_active_fd < 0);
1242
1243         /* On certain architectures (S390 and Xen, and containers),
1244            /dev/tty0 does not exist, so don't fail if we can't open
1245            it. */
1246         if (access("/dev/tty0", F_OK) < 0) {
1247                 m->console_active_fd = -1;
1248                 return 0;
1249         }
1250
1251         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1252         if (m->console_active_fd < 0) {
1253
1254                 /* On some systems the device node /dev/tty0 may exist
1255                  * even though /sys/class/tty/tty0 does not. */
1256                 if (errno == ENOENT)
1257                         return 0;
1258
1259                 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1260                 return -errno;
1261         }
1262
1263         zero(ev);
1264         ev.events = 0;
1265         ev.data.u32 = FD_CONSOLE;
1266
1267         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1268                 return -errno;
1269
1270         return 0;
1271 }
1272
1273 static int manager_connect_udev(Manager *m) {
1274         struct epoll_event ev;
1275         int r;
1276
1277         assert(m);
1278         assert(!m->udev_seat_monitor);
1279         assert(!m->udev_vcsa_monitor);
1280         assert(!m->udev_button_monitor);
1281
1282         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1283         if (!m->udev_seat_monitor)
1284                 return -ENOMEM;
1285
1286         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1287         if (r < 0)
1288                 return r;
1289
1290         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1291         if (r < 0)
1292                 return r;
1293
1294         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1295         if (r < 0)
1296                 return r;
1297
1298         m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1299
1300         zero(ev);
1301         ev.events = EPOLLIN;
1302         ev.data.u32 = FD_SEAT_UDEV;
1303         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1304                 return -errno;
1305
1306         /* Don't watch keys if nobody cares */
1307         if (m->handle_power_key != HANDLE_OFF ||
1308             m->handle_sleep_key != HANDLE_OFF ||
1309             m->handle_lid_switch != HANDLE_OFF) {
1310
1311                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1312                 if (!m->udev_button_monitor)
1313                         return -ENOMEM;
1314
1315                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1316                 if (r < 0)
1317                         return r;
1318
1319                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1320                 if (r < 0)
1321                         return r;
1322
1323                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1324                 if (r < 0)
1325                         return r;
1326
1327                 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1328
1329                 zero(ev);
1330                 ev.events = EPOLLIN;
1331                 ev.data.u32 = FD_BUTTON_UDEV;
1332                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1333                         return -errno;
1334         }
1335
1336         /* Don't bother watching VCSA devices, if nobody cares */
1337         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1338
1339                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1340                 if (!m->udev_vcsa_monitor)
1341                         return -ENOMEM;
1342
1343                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1344                 if (r < 0)
1345                         return r;
1346
1347                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1348                 if (r < 0)
1349                         return r;
1350
1351                 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1352
1353                 zero(ev);
1354                 ev.events = EPOLLIN;
1355                 ev.data.u32 = FD_VCSA_UDEV;
1356                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1357                         return -errno;
1358         }
1359
1360         return 0;
1361 }
1362
1363 void manager_gc(Manager *m, bool drop_not_started) {
1364         Seat *seat;
1365         Session *session;
1366         User *user;
1367
1368         assert(m);
1369
1370         while ((seat = m->seat_gc_queue)) {
1371                 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1372                 seat->in_gc_queue = false;
1373
1374                 if (seat_check_gc(seat, drop_not_started) == 0) {
1375                         seat_stop(seat);
1376                         seat_free(seat);
1377                 }
1378         }
1379
1380         while ((session = m->session_gc_queue)) {
1381                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1382                 session->in_gc_queue = false;
1383
1384                 if (session_check_gc(session, drop_not_started) == 0) {
1385                         session_stop(session);
1386                         session_free(session);
1387                 }
1388         }
1389
1390         while ((user = m->user_gc_queue)) {
1391                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1392                 user->in_gc_queue = false;
1393
1394                 if (user_check_gc(user, drop_not_started) == 0) {
1395                         user_stop(user);
1396                         user_free(user);
1397                 }
1398         }
1399 }
1400
1401 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1402         Session *s;
1403         bool idle_hint;
1404         dual_timestamp ts = { 0, 0 };
1405         Iterator i;
1406
1407         assert(m);
1408
1409         idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
1410
1411         HASHMAP_FOREACH(s, m->sessions, i) {
1412                 dual_timestamp k;
1413                 int ih;
1414
1415                 ih = session_get_idle_hint(s, &k);
1416                 if (ih < 0)
1417                         return ih;
1418
1419                 if (!ih) {
1420                         if (!idle_hint) {
1421                                 if (k.monotonic < ts.monotonic)
1422                                         ts = k;
1423                         } else {
1424                                 idle_hint = false;
1425                                 ts = k;
1426                         }
1427                 } else if (idle_hint) {
1428
1429                         if (k.monotonic > ts.monotonic)
1430                                 ts = k;
1431                 }
1432         }
1433
1434         if (t)
1435                 *t = ts;
1436
1437         return idle_hint;
1438 }
1439
1440 int manager_startup(Manager *m) {
1441         int r;
1442         Seat *seat;
1443         Session *session;
1444         User *user;
1445         Inhibitor *inhibitor;
1446         Iterator i;
1447
1448         assert(m);
1449         assert(m->epoll_fd <= 0);
1450
1451         cg_shorten_controllers(m->reset_controllers);
1452         cg_shorten_controllers(m->controllers);
1453
1454         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1455         if (m->epoll_fd < 0)
1456                 return -errno;
1457
1458         /* Connect to console */
1459         r = manager_connect_console(m);
1460         if (r < 0)
1461                 return r;
1462
1463         /* Connect to udev */
1464         r = manager_connect_udev(m);
1465         if (r < 0)
1466                 return r;
1467
1468         /* Connect to the bus */
1469         r = manager_connect_bus(m);
1470         if (r < 0)
1471                 return r;
1472
1473         /* Instantiate magic seat 0 */
1474         r = manager_add_seat(m, "seat0", &m->vtconsole);
1475         if (r < 0)
1476                 return r;
1477
1478         /* Deserialize state */
1479         manager_enumerate_devices(m);
1480         manager_enumerate_seats(m);
1481         manager_enumerate_users(m);
1482         manager_enumerate_sessions(m);
1483         manager_enumerate_inhibitors(m);
1484         manager_enumerate_buttons(m);
1485
1486         /* Remove stale objects before we start them */
1487         manager_gc(m, false);
1488
1489         /* Reserve the special reserved VT */
1490         manager_reserve_vt(m);
1491
1492         /* And start everything */
1493         HASHMAP_FOREACH(seat, m->seats, i)
1494                 seat_start(seat);
1495
1496         HASHMAP_FOREACH(user, m->users, i)
1497                 user_start(user);
1498
1499         HASHMAP_FOREACH(session, m->sessions, i)
1500                 session_start(session);
1501
1502         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1503                 inhibitor_start(inhibitor);
1504
1505         return 0;
1506 }
1507
1508 int manager_run(Manager *m) {
1509         assert(m);
1510
1511         for (;;) {
1512                 struct epoll_event event;
1513                 int n;
1514                 int msec = -1;
1515
1516                 manager_gc(m, true);
1517
1518                 if (manager_dispatch_delayed(m) > 0)
1519                         continue;
1520
1521                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1522                         continue;
1523
1524                 manager_gc(m, true);
1525
1526                 if (m->delayed_unit) {
1527                         usec_t x, y;
1528
1529                         x = now(CLOCK_MONOTONIC);
1530                         y = m->delayed_timestamp + m->inhibit_delay_max;
1531
1532                         msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1533                 }
1534
1535                 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1536                 if (n < 0) {
1537                         if (errno == EINTR || errno == EAGAIN)
1538                                 continue;
1539
1540                         log_error("epoll() failed: %m");
1541                         return -errno;
1542                 }
1543
1544                 if (n == 0)
1545                         continue;
1546
1547                 switch (event.data.u32) {
1548
1549                 case FD_SEAT_UDEV:
1550                         manager_dispatch_seat_udev(m);
1551                         break;
1552
1553                 case FD_VCSA_UDEV:
1554                         manager_dispatch_vcsa_udev(m);
1555                         break;
1556
1557                 case FD_BUTTON_UDEV:
1558                         manager_dispatch_button_udev(m);
1559                         break;
1560
1561                 case FD_CONSOLE:
1562                         manager_dispatch_console(m);
1563                         break;
1564
1565                 case FD_BUS:
1566                         bus_loop_dispatch(m->bus_fd);
1567                         break;
1568
1569                 default:
1570                         if (event.data.u32 >= FD_OTHER_BASE)
1571                                 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1572                 }
1573         }
1574
1575         return 0;
1576 }
1577
1578 static int manager_parse_config_file(Manager *m) {
1579         FILE *f;
1580         const char *fn;
1581         int r;
1582
1583         assert(m);
1584
1585         fn = "/etc/systemd/logind.conf";
1586         f = fopen(fn, "re");
1587         if (!f) {
1588                 if (errno == ENOENT)
1589                         return 0;
1590
1591                 log_warning("Failed to open configuration file %s: %m", fn);
1592                 return -errno;
1593         }
1594
1595         r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1596         if (r < 0)
1597                 log_warning("Failed to parse configuration file: %s", strerror(-r));
1598
1599         fclose(f);
1600
1601         return r;
1602 }
1603
1604 int main(int argc, char *argv[]) {
1605         Manager *m = NULL;
1606         int r;
1607
1608         log_set_target(LOG_TARGET_AUTO);
1609         log_set_facility(LOG_AUTH);
1610         log_parse_environment();
1611         log_open();
1612
1613         umask(0022);
1614
1615         if (argc != 1) {
1616                 log_error("This program takes no arguments.");
1617                 r = -EINVAL;
1618                 goto finish;
1619         }
1620
1621         m = manager_new();
1622         if (!m) {
1623                 r = log_oom();
1624                 goto finish;
1625         }
1626
1627         manager_parse_config_file(m);
1628
1629         r = manager_startup(m);
1630         if (r < 0) {
1631                 log_error("Failed to fully start up daemon: %s", strerror(-r));
1632                 goto finish;
1633         }
1634
1635         log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1636
1637         sd_notify(false,
1638                   "READY=1\n"
1639                   "STATUS=Processing requests...");
1640
1641         r = manager_run(m);
1642
1643         log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1644
1645 finish:
1646         sd_notify(false,
1647                   "STATUS=Shutting down...");
1648
1649         if (m)
1650                 manager_free(m);
1651
1652         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1653 }