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