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