]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind.c
Describe handling of an AF_UNIX socket
[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) {
4470d841 600 _cleanup_closedir_ DIR *d = NULL;
f8e2fb7b 601 int r = 0, k;
20263082 602 char *name;
20263082
LP
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;
4470d841 615 char *e;
14c3baca 616
4470d841
LP
617 e = endswith(name, ".user");
618 if (e) {
619 *e = 0;
14c3baca 620
4470d841
LP
621 k = manager_add_user_by_name(m, name, &user);
622 if (k < 0) {
14c3baca 623 free(name);
4470d841
LP
624 r = k;
625 continue;
14c3baca 626 }
20263082 627
4470d841
LP
628 user_add_to_gc_queue(user);
629
630 if (!user->cgroup_path) {
631 user->cgroup_path = strjoin(m->cgroup_path, "/", name, NULL);
632 if (!user->cgroup_path) {
633 k = log_oom();
634 free(name);
635 break;
636 }
637 }
638 }
639
20263082 640 free(name);
14c3baca
LP
641 }
642
4470d841 643 if (k < 0)
3e085b6c
LP
644 r = k;
645
14c3baca
LP
646 return r;
647}
20263082 648
14c3baca
LP
649static int manager_enumerate_linger_users(Manager *m) {
650 DIR *d;
651 struct dirent *de;
652 int r = 0;
653
654 d = opendir("/var/lib/systemd/linger");
655 if (!d) {
656 if (errno == ENOENT)
657 return 0;
658
659 log_error("Failed to open /var/lib/systemd/linger/: %m");
660 return -errno;
661 }
662
663 while ((de = readdir(d))) {
664 int k;
665
666 if (!dirent_is_file(de))
20263082
LP
667 continue;
668
14c3baca
LP
669 k = manager_add_user_by_name(m, de->d_name, NULL);
670 if (k < 0) {
671 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
672 r = k;
20263082
LP
673 }
674 }
675
14c3baca 676 closedir(d);
20263082
LP
677
678 return r;
679}
680
681int manager_enumerate_users(Manager *m) {
682 DIR *d;
683 struct dirent *de;
14c3baca 684 int r, k;
20263082
LP
685
686 assert(m);
687
14c3baca 688 /* First, enumerate user cgroups */
20263082
LP
689 r = manager_enumerate_users_from_cgroup(m);
690
14c3baca
LP
691 /* Second, add lingering users on top */
692 k = manager_enumerate_linger_users(m);
693 if (k < 0)
694 r = k;
695
696 /* Third, read in user data stored on disk */
20263082
LP
697 d = opendir("/run/systemd/users");
698 if (!d) {
699 if (errno == ENOENT)
700 return 0;
701
702 log_error("Failed to open /run/systemd/users: %m");
703 return -errno;
704 }
705
706 while ((de = readdir(d))) {
ddd88763 707 uid_t uid;
20263082 708 User *u;
20263082
LP
709
710 if (!dirent_is_file(de))
711 continue;
712
ddd88763 713 k = parse_uid(de->d_name, &uid);
20263082
LP
714 if (k < 0) {
715 log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
716 continue;
717 }
718
ddd88763 719 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
20263082
LP
720 if (!u) {
721 unlinkat(dirfd(d), de->d_name, 0);
722 continue;
723 }
724
725 k = user_load(u);
726 if (k < 0)
727 r = k;
728 }
729
730 closedir(d);
731
732 return r;
733}
734
735static int manager_enumerate_sessions_from_cgroup(Manager *m) {
736 User *u;
737 Iterator i;
738 int r = 0;
739
740 HASHMAP_FOREACH(u, m->users, i) {
4470d841 741 _cleanup_closedir_ DIR *d = NULL;
20263082
LP
742 char *name;
743 int k;
744
14c3baca
LP
745 if (!u->cgroup_path)
746 continue;
747
20263082
LP
748 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
749 if (k < 0) {
750 if (k == -ENOENT)
751 continue;
752
753 log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
754 r = k;
755 continue;
756 }
757
758 while ((k = cg_read_subgroup(d, &name)) > 0) {
759 Session *session;
4470d841 760 char *e;
20263082 761
4470d841
LP
762 e = endswith(name, ".session");
763 if (e) {
764 *e = 0;
11896841 765
4470d841
LP
766 k = manager_add_session(m, u, name, &session);
767 if (k < 0) {
768 free(name);
769 r = k;
770 continue;
771 }
20263082 772
4470d841 773 session_add_to_gc_queue(session);
20263082 774
4470d841
LP
775 if (!session->cgroup_path) {
776 session->cgroup_path = strjoin(m->cgroup_path, "/", name, NULL);
777 if (!session->cgroup_path) {
778 k = log_oom();
779 free(name);
780 break;
781 }
14c3baca 782 }
4470d841 783 }
14c3baca
LP
784
785 free(name);
20263082
LP
786 }
787
20263082
LP
788 if (k < 0)
789 r = k;
790 }
791
792 return r;
793}
794
795int manager_enumerate_sessions(Manager *m) {
796 DIR *d;
797 struct dirent *de;
798 int r = 0;
799
800 assert(m);
801
14c3baca 802 /* First enumerate session cgroups */
20263082
LP
803 r = manager_enumerate_sessions_from_cgroup(m);
804
14c3baca 805 /* Second, read in session data stored on disk */
20263082
LP
806 d = opendir("/run/systemd/sessions");
807 if (!d) {
808 if (errno == ENOENT)
809 return 0;
810
811 log_error("Failed to open /run/systemd/sessions: %m");
812 return -errno;
813 }
814
815 while ((de = readdir(d))) {
816 struct Session *s;
817 int k;
818
819 if (!dirent_is_file(de))
820 continue;
821
822 s = hashmap_get(m->sessions, de->d_name);
823 if (!s) {
824 unlinkat(dirfd(d), de->d_name, 0);
825 continue;
826 }
827
828 k = session_load(s);
829 if (k < 0)
830 r = k;
831 }
832
833 closedir(d);
834
835 return r;
836}
837
f8e2fb7b
LP
838int manager_enumerate_inhibitors(Manager *m) {
839 DIR *d;
840 struct dirent *de;
841 int r = 0;
842
843 assert(m);
844
845 d = opendir("/run/systemd/inhibit");
846 if (!d) {
847 if (errno == ENOENT)
848 return 0;
849
850 log_error("Failed to open /run/systemd/inhibit: %m");
851 return -errno;
852 }
853
854 while ((de = readdir(d))) {
855 int k;
856 Inhibitor *i;
857
858 if (!dirent_is_file(de))
859 continue;
860
861 k = manager_add_inhibitor(m, de->d_name, &i);
862 if (k < 0) {
863 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
864 r = k;
865 continue;
866 }
867
868 k = inhibitor_load(i);
869 if (k < 0)
870 r = k;
871 }
872
873 closedir(d);
874
875 return r;
876}
877
30ed21ce 878int manager_dispatch_seat_udev(Manager *m) {
20263082
LP
879 struct udev_device *d;
880 int r;
881
882 assert(m);
883
30ed21ce 884 d = udev_monitor_receive_device(m->udev_seat_monitor);
20263082
LP
885 if (!d)
886 return -ENOMEM;
887
30ed21ce
LP
888 r = manager_process_seat_device(m, d);
889 udev_device_unref(d);
890
891 return r;
892}
893
30ed21ce
LP
894int manager_dispatch_vcsa_udev(Manager *m) {
895 struct udev_device *d;
896 int r = 0;
897 const char *name;
898
899 assert(m);
900
901 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
902 if (!d)
903 return -ENOMEM;
904
905 name = udev_device_get_sysname(d);
906
907 /* Whenever a VCSA device is removed try to reallocate our
908 * VTs, to make sure our auto VTs never go away. */
909
910 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
911 r = seat_preallocate_vts(m->vtconsole);
912
20263082
LP
913 udev_device_unref(d);
914
915 return r;
916}
917
069cfc85
LP
918int manager_dispatch_button_udev(Manager *m) {
919 struct udev_device *d;
920 int r;
921
922 assert(m);
923
924 d = udev_monitor_receive_device(m->udev_button_monitor);
925 if (!d)
926 return -ENOMEM;
927
928 r = manager_process_button_device(m, d);
929 udev_device_unref(d);
930
931 return r;
932}
933
20263082 934int manager_dispatch_console(Manager *m) {
20263082
LP
935 assert(m);
936
20263082 937 if (m->vtconsole)
14c3baca 938 seat_read_active_vt(m->vtconsole);
20263082
LP
939
940 return 0;
941}
942
5eda94dd
LP
943static int vt_is_busy(int vtnr) {
944 struct vt_stat vt_stat;
945 int r = 0, fd;
946
947 assert(vtnr >= 1);
948
d0a522eb
LP
949 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
950 * we'd open the latter we'd open the foreground tty which
951 * hence would be unconditionally busy. By opening /dev/tty1
952 * we avoid this. Since tty1 is special and needs to be an
953 * explicitly loaded getty or DM this is safe. */
954
955 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
5eda94dd
LP
956 if (fd < 0)
957 return -errno;
958
959 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
960 r = -errno;
961 else
962 r = !!(vt_stat.v_state & (1 << vtnr));
963
964 close_nointr_nofail(fd);
965
966 return r;
967}
968
20263082 969int manager_spawn_autovt(Manager *m, int vtnr) {
5eda94dd 970 int r;
d0a522eb
LP
971 char *name = NULL;
972 const char *mode = "fail";
5eda94dd 973
20263082 974 assert(m);
30ed21ce 975 assert(vtnr >= 1);
20263082 976
98a77df5
LP
977 if ((unsigned) vtnr > m->n_autovts &&
978 (unsigned) vtnr != m->reserve_vt)
975fd867
LP
979 return 0;
980
98a77df5
LP
981 if ((unsigned) vtnr != m->reserve_vt) {
982 /* If this is the reserved TTY, we'll start the getty
983 * on it in any case, but otherwise only if it is not
984 * busy. */
985
986 r = vt_is_busy(vtnr);
987 if (r < 0)
988 return r;
989 else if (r > 0)
990 return -EBUSY;
991 }
5eda94dd 992
cd9e5d0a 993 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
d0a522eb
LP
994 log_error("Could not allocate service name.");
995 r = -ENOMEM;
996 goto finish;
997 }
98a77df5 998
b9c26b41
SP
999 r = bus_method_call_with_reply (
1000 m->bus,
1001 "org.freedesktop.systemd1",
1002 "/org/freedesktop/systemd1",
1003 "org.freedesktop.systemd1.Manager",
1004 "StartUnit",
1005 NULL,
1006 NULL,
1007 DBUS_TYPE_STRING, &name,
1008 DBUS_TYPE_STRING, &mode,
1009 DBUS_TYPE_INVALID);
d0a522eb
LP
1010
1011finish:
1012 free(name);
1013
d0a522eb 1014 return r;
20263082
LP
1015}
1016
98a77df5
LP
1017static int manager_reserve_vt(Manager *m) {
1018 _cleanup_free_ char *p = NULL;
1019
1020 assert(m);
1021
1022 if (m->reserve_vt <= 0)
1023 return 0;
1024
1025 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1026 return log_oom();
1027
1028 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1029 if (m->reserve_vt_fd < 0) {
d4d882e5
LP
1030
1031 /* Don't complain on VT-less systems */
1032 if (errno != ENOENT)
1033 log_warning("Failed to pin reserved VT: %m");
98a77df5
LP
1034 return -errno;
1035 }
1036
1037 return 0;
1038}
1039
9b221b63 1040int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
acb14d31 1041 Session *s;
1713813d
LP
1042 char *p;
1043
1044 assert(m);
1045 assert(cgroup);
9b221b63 1046 assert(session);
1713813d 1047
8c8c4351 1048 s = hashmap_get(m->session_cgroups, cgroup);
acb14d31
LP
1049 if (s) {
1050 *session = s;
1051 return 1;
1052 }
1053
54b758dd 1054 p = strdupa(cgroup);
1713813d
LP
1055
1056 for (;;) {
1057 char *e;
20263082 1058
acb14d31
LP
1059 e = strrchr(p, '/');
1060 if (!e || e == p) {
9b221b63
LP
1061 *session = NULL;
1062 return 0;
1063 }
1713813d 1064
acb14d31
LP
1065 *e = 0;
1066
8c8c4351 1067 s = hashmap_get(m->session_cgroups, p);
9b221b63 1068 if (s) {
9b221b63
LP
1069 *session = s;
1070 return 1;
1071 }
1713813d 1072 }
9b221b63
LP
1073}
1074
8c8c4351
LP
1075int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1076 User *u;
1077 char *p;
1078
1079 assert(m);
1080 assert(cgroup);
1081 assert(user);
1082
1083 u = hashmap_get(m->user_cgroups, cgroup);
1084 if (u) {
1085 *user = u;
1086 return 1;
1087 }
1088
54b758dd 1089 p = strdupa(cgroup);
0d0f0c50
SL
1090 if (!p)
1091 return log_oom();
8c8c4351
LP
1092
1093 for (;;) {
1094 char *e;
1095
1096 e = strrchr(p, '/');
1097 if (!e || e == p) {
8c8c4351
LP
1098 *user = NULL;
1099 return 0;
1100 }
1101
1102 *e = 0;
1103
1104 u = hashmap_get(m->user_cgroups, p);
1105 if (u) {
8c8c4351
LP
1106 *user = u;
1107 return 1;
1108 }
1109 }
1110}
1111
9b221b63 1112int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
7027ff61 1113 _cleanup_free_ char *p = NULL;
9b221b63
LP
1114 int r;
1115
1116 assert(m);
1117 assert(pid >= 1);
1118 assert(session);
1713813d 1119
7027ff61 1120 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
9b221b63
LP
1121 if (r < 0)
1122 return r;
1123
7027ff61 1124 return manager_get_session_by_cgroup(m, p, session);
9b221b63
LP
1125}
1126
1127void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1128 Session *s;
8c8c4351 1129 User *u;
9b221b63
LP
1130 int r;
1131
1132 r = manager_get_session_by_cgroup(m, cgroup, &s);
8c8c4351
LP
1133 if (r > 0)
1134 session_add_to_gc_queue(s);
9b221b63 1135
8c8c4351
LP
1136 r = manager_get_user_by_cgroup(m, cgroup, &u);
1137 if (r > 0)
1138 user_add_to_gc_queue(u);
20263082
LP
1139}
1140
069cfc85 1141static void manager_dispatch_other(Manager *m, int fd) {
31b79c2b 1142 Session *s;
f8e2fb7b 1143 Inhibitor *i;
069cfc85 1144 Button *b;
31b79c2b
LP
1145
1146 assert_se(m);
1147 assert_se(fd >= 0);
1148
f8e2fb7b
LP
1149 s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1150 if (s) {
1151 assert(s->fifo_fd == fd);
1152 session_remove_fifo(s);
1153 session_stop(s);
1154 return;
1155 }
31b79c2b 1156
f8e2fb7b
LP
1157 i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1158 if (i) {
1159 assert(i->fifo_fd == fd);
1160 inhibitor_stop(i);
1161 inhibitor_free(i);
1162 return;
1163 }
1164
069cfc85
LP
1165 b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1166 if (b) {
1167 assert(b->fd == fd);
1168 button_process(b);
1169 return;
1170 }
1171
1172 assert_not_reached("Got event for unknown fd");
31b79c2b
LP
1173}
1174
20263082 1175static int manager_connect_bus(Manager *m) {
20263082
LP
1176 DBusError error;
1177 int r;
b92bea5d
ZJS
1178 struct epoll_event ev = {
1179 .events = EPOLLIN,
1180 .data.u32 = FD_BUS,
1181 };
20263082
LP
1182
1183 assert(m);
1184 assert(!m->bus);
1185 assert(m->bus_fd < 0);
1186
1187 dbus_error_init(&error);
1188
1189 m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1190 if (!m->bus) {
a2e52832 1191 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
20263082
LP
1192 r = -ECONNREFUSED;
1193 goto fail;
1194 }
1195
3f49d45a
LP
1196 if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1197 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1198 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1199 !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1713813d 1200 !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
0d0f0c50 1201 r = log_oom();
20263082
LP
1202 goto fail;
1203 }
1204
1205 dbus_bus_add_match(m->bus,
1206 "type='signal',"
1207 "interface='org.freedesktop.systemd1.Agent',"
1208 "member='Released',"
1209 "path='/org/freedesktop/systemd1/agent'",
1210 &error);
1211
1212 if (dbus_error_is_set(&error)) {
a2e52832 1213 log_error("Failed to register match: %s", bus_error_message(&error));
20263082
LP
1214 r = -EIO;
1215 goto fail;
1216 }
1217
bafd4449
LP
1218 r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1219 if (dbus_error_is_set(&error)) {
1220 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1221 r = -EIO;
1222 goto fail;
1223 }
1224
1225 if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1226 log_error("Failed to acquire name.");
20263082
LP
1227 r = -EEXIST;
1228 goto fail;
1229 }
1230
1231 m->bus_fd = bus_loop_open(m->bus);
1232 if (m->bus_fd < 0) {
1233 r = m->bus_fd;
1234 goto fail;
1235 }
1236
20263082
LP
1237 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1238 goto fail;
1239
1240 return 0;
1241
1242fail:
1243 dbus_error_free(&error);
1244
1245 return r;
1246}
1247
1248static int manager_connect_console(Manager *m) {
b92bea5d
ZJS
1249 struct epoll_event ev = {
1250 .events = 0,
1251 .data.u32 = FD_CONSOLE,
1252 };
20263082
LP
1253
1254 assert(m);
1255 assert(m->console_active_fd < 0);
1256
74afee9c
LP
1257 /* On certain architectures (S390 and Xen, and containers),
1258 /dev/tty0 does not exist, so don't fail if we can't open
1259 it. */
1260 if (access("/dev/tty0", F_OK) < 0) {
1261 m->console_active_fd = -1;
1262 return 0;
1263 }
1264
20263082
LP
1265 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1266 if (m->console_active_fd < 0) {
cdc564d2
MS
1267
1268 /* On some systems the device node /dev/tty0 may exist
1269 * even though /sys/class/tty/tty0 does not. */
1270 if (errno == ENOENT)
1271 return 0;
1272
20263082
LP
1273 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1274 return -errno;
1275 }
1276
20263082
LP
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) {
14c3baca 1284 int r;
b92bea5d
ZJS
1285 struct epoll_event ev = {
1286 .events = EPOLLIN,
1287 .data.u32 = FD_SEAT_UDEV,
1288 };
20263082
LP
1289
1290 assert(m);
30ed21ce
LP
1291 assert(!m->udev_seat_monitor);
1292 assert(!m->udev_vcsa_monitor);
069cfc85 1293 assert(!m->udev_button_monitor);
20263082 1294
30ed21ce
LP
1295 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1296 if (!m->udev_seat_monitor)
20263082
LP
1297 return -ENOMEM;
1298
2d96536d 1299 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
14c3baca
LP
1300 if (r < 0)
1301 return r;
20263082 1302
30ed21ce 1303 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
14c3baca
LP
1304 if (r < 0)
1305 return r;
20263082 1306
30ed21ce 1307 m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
20263082 1308
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;
b92bea5d 1449 struct itimerspec its = {};
23406ce5
LP
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
23406ce5
LP
1461 n = now(CLOCK_MONOTONIC);
1462
1463 r = manager_get_idle_hint(m, &since);
1464 if (r <= 0)
39ccc87c 1465 /* Not idle. Let's check if after a timeout it might be idle then. */
23406ce5
LP
1466 timespec_store(&its.it_value, n + m->idle_action_usec);
1467 else {
1468 /* Idle! Let's see if it's time to do something, or if
1469 * we shall sleep for longer. */
1470
1471 if (n >= since.monotonic + m->idle_action_usec &&
1472 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1473 log_info("System idle. Taking action.");
1474
1475 manager_handle_action(m, 0, m->idle_action, false, false);
1476 m->idle_action_not_before_usec = n;
1477 }
1478
1479 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1480 }
1481
1482 if (m->idle_action_fd < 0) {
b92bea5d
ZJS
1483 struct epoll_event ev = {
1484 .events = EPOLLIN,
1485 .data.u32 = FD_IDLE_ACTION,
1486 };
23406ce5
LP
1487
1488 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1489 if (m->idle_action_fd < 0) {
1490 log_error("Failed to create idle action timer: %m");
1491 r = -errno;
1492 goto finish;
1493 }
1494
23406ce5
LP
1495 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1496 log_error("Failed to add idle action timer to epoll: %m");
1497 r = -errno;
1498 goto finish;
1499 }
1500 }
1501
1502 if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1503 log_error("Failed to reset timerfd: %m");
1504 r = -errno;
1505 goto finish;
1506 }
1507
1508 return 0;
1509
1510finish:
1511 if (m->idle_action_fd >= 0) {
1512 close_nointr_nofail(m->idle_action_fd);
1513 m->idle_action_fd = -1;
1514 }
1515
1516 return r;
1517}
20263082
LP
1518int manager_startup(Manager *m) {
1519 int r;
14c3baca
LP
1520 Seat *seat;
1521 Session *session;
1522 User *user;
f8e2fb7b 1523 Inhibitor *inhibitor;
14c3baca 1524 Iterator i;
20263082
LP
1525
1526 assert(m);
1527 assert(m->epoll_fd <= 0);
1528
b59e2465
LP
1529 cg_shorten_controllers(m->reset_controllers);
1530 cg_shorten_controllers(m->controllers);
1531
20263082
LP
1532 m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1533 if (m->epoll_fd < 0)
1534 return -errno;
1535
976c088a
LP
1536 /* Connect to console */
1537 r = manager_connect_console(m);
20263082
LP
1538 if (r < 0)
1539 return r;
1540
976c088a
LP
1541 /* Connect to udev */
1542 r = manager_connect_udev(m);
20263082
LP
1543 if (r < 0)
1544 return r;
1545
1546 /* Connect to the bus */
1547 r = manager_connect_bus(m);
1548 if (r < 0)
1549 return r;
1550
14c3baca
LP
1551 /* Instantiate magic seat 0 */
1552 r = manager_add_seat(m, "seat0", &m->vtconsole);
1553 if (r < 0)
1554 return r;
1555
20263082
LP
1556 /* Deserialize state */
1557 manager_enumerate_devices(m);
1558 manager_enumerate_seats(m);
1559 manager_enumerate_users(m);
1560 manager_enumerate_sessions(m);
f8e2fb7b 1561 manager_enumerate_inhibitors(m);
069cfc85 1562 manager_enumerate_buttons(m);
20263082 1563
4a4b033f
LP
1564 /* Remove stale objects before we start them */
1565 manager_gc(m, false);
1566
98a77df5
LP
1567 /* Reserve the special reserved VT */
1568 manager_reserve_vt(m);
1569
14c3baca
LP
1570 /* And start everything */
1571 HASHMAP_FOREACH(seat, m->seats, i)
1572 seat_start(seat);
1573
1574 HASHMAP_FOREACH(user, m->users, i)
1575 user_start(user);
1576
1577 HASHMAP_FOREACH(session, m->sessions, i)
1578 session_start(session);
20263082 1579
f8e2fb7b
LP
1580 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1581 inhibitor_start(inhibitor);
1582
23406ce5
LP
1583 manager_dispatch_idle_action(m);
1584
20263082
LP
1585 return 0;
1586}
1587
65b51162
LP
1588static int manager_recheck_buttons(Manager *m) {
1589 Iterator i;
1590 Button *b;
1591 int r = 0;
1592
1593 assert(m);
1594
1595 HASHMAP_FOREACH(b, m->buttons, i) {
1596 int q;
1597
1598 q = button_recheck(b);
1599 if (q > 0)
1600 return 1;
1601 if (q < 0)
1602 r = q;
1603 }
1604
1605 return r;
1606}
1607
20263082
LP
1608int manager_run(Manager *m) {
1609 assert(m);
1610
1611 for (;;) {
1612 struct epoll_event event;
1613 int n;
eecd1362 1614 int msec = -1;
20263082 1615
4a4b033f 1616 manager_gc(m, true);
14c3baca 1617
d889a206 1618 if (manager_dispatch_delayed(m) > 0)
eecd1362
LP
1619 continue;
1620
65b51162
LP
1621 if (manager_recheck_buttons(m) > 0)
1622 continue;
1623
20263082
LP
1624 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1625 continue;
1626
4a4b033f 1627 manager_gc(m, true);
1713813d 1628
84286536 1629 if (m->action_what != 0 && !m->action_job) {
eecd1362
LP
1630 usec_t x, y;
1631
1632 x = now(CLOCK_MONOTONIC);
314b4b0a 1633 y = m->action_timestamp + m->inhibit_delay_max;
eecd1362
LP
1634
1635 msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1636 }
1637
1638 n = epoll_wait(m->epoll_fd, &event, 1, msec);
20263082 1639 if (n < 0) {
3f49d45a
LP
1640 if (errno == EINTR || errno == EAGAIN)
1641 continue;
1642
20263082
LP
1643 log_error("epoll() failed: %m");
1644 return -errno;
1645 }
1646
eecd1362
LP
1647 if (n == 0)
1648 continue;
1649
20263082
LP
1650 switch (event.data.u32) {
1651
30ed21ce
LP
1652 case FD_SEAT_UDEV:
1653 manager_dispatch_seat_udev(m);
1654 break;
1655
1656 case FD_VCSA_UDEV:
1657 manager_dispatch_vcsa_udev(m);
20263082
LP
1658 break;
1659
069cfc85
LP
1660 case FD_BUTTON_UDEV:
1661 manager_dispatch_button_udev(m);
1662 break;
1663
20263082
LP
1664 case FD_CONSOLE:
1665 manager_dispatch_console(m);
1666 break;
1667
23406ce5
LP
1668 case FD_IDLE_ACTION:
1669 manager_dispatch_idle_action(m);
1670 break;
1671
20263082
LP
1672 case FD_BUS:
1673 bus_loop_dispatch(m->bus_fd);
1674 break;
31b79c2b
LP
1675
1676 default:
069cfc85
LP
1677 if (event.data.u32 >= FD_OTHER_BASE)
1678 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
20263082
LP
1679 }
1680 }
1681
1682 return 0;
1683}
1684
193197e8 1685static int manager_parse_config_file(Manager *m) {
db5c0122
LP
1686 static const char fn[] = "/etc/systemd/logind.conf";
1687 _cleanup_fclose_ FILE *f = NULL;
193197e8
LP
1688 int r;
1689
1690 assert(m);
1691
193197e8
LP
1692 f = fopen(fn, "re");
1693 if (!f) {
1694 if (errno == ENOENT)
1695 return 0;
1696
1697 log_warning("Failed to open configuration file %s: %m", fn);
1698 return -errno;
1699 }
1700
db5c0122
LP
1701 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1702 (void*) logind_gperf_lookup, false, false, m);
193197e8
LP
1703 if (r < 0)
1704 log_warning("Failed to parse configuration file: %s", strerror(-r));
1705
193197e8
LP
1706 return r;
1707}
1708
20263082
LP
1709int main(int argc, char *argv[]) {
1710 Manager *m = NULL;
5eda94dd 1711 int r;
20263082
LP
1712
1713 log_set_target(LOG_TARGET_AUTO);
3eff4208 1714 log_set_facility(LOG_AUTH);
20263082
LP
1715 log_parse_environment();
1716 log_open();
1717
4c12626c
LP
1718 umask(0022);
1719
20263082
LP
1720 if (argc != 1) {
1721 log_error("This program takes no arguments.");
1722 r = -EINVAL;
1723 goto finish;
1724 }
1725
bb27ff66
LP
1726 /* Always create the directories people can create inotify
1727 * watches in. Note that some applications might check for the
ab06eef8 1728 * existence of /run/systemd/seats/ to determine whether
bb27ff66
LP
1729 * logind is available, so please always make sure this check
1730 * stays in. */
1731 mkdir_label("/run/systemd/seats", 0755);
1732 mkdir_label("/run/systemd/users", 0755);
1733 mkdir_label("/run/systemd/sessions", 0755);
1734
20263082
LP
1735 m = manager_new();
1736 if (!m) {
0d0f0c50 1737 r = log_oom();
20263082
LP
1738 goto finish;
1739 }
1740
193197e8
LP
1741 manager_parse_config_file(m);
1742
20263082
LP
1743 r = manager_startup(m);
1744 if (r < 0) {
1745 log_error("Failed to fully start up daemon: %s", strerror(-r));
1746 goto finish;
1747 }
1748
e6960940
LP
1749 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1750
1751 sd_notify(false,
1752 "READY=1\n"
1753 "STATUS=Processing requests...");
1754
20263082
LP
1755 r = manager_run(m);
1756
e6960940
LP
1757 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1758
20263082 1759finish:
e6960940
LP
1760 sd_notify(false,
1761 "STATUS=Shutting down...");
1762
20263082
LP
1763 if (m)
1764 manager_free(m);
1765
1766 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1767}