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