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