]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind.c
3f71f5b4a9e5c4a4457de170ec2fd91e0b56104d
[thirdparty/systemd.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 }