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