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