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