]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind.c
git: update .gitignore
[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>
20263082
LP
23#include <libudev.h>
24#include <fcntl.h>
25#include <string.h>
26#include <unistd.h>
5eda94dd 27#include <linux/vt.h>
23406ce5 28#include <sys/timerfd.h>
20263082 29
cc377381 30#include "sd-daemon.h"
193197e8
LP
31#include "strv.h"
32#include "conf-parser.h"
bb27ff66 33#include "mkdir.h"
cc377381
LP
34#include "bus-util.h"
35#include "bus-error.h"
36#include "logind.h"
20263082 37
20263082
LP
38Manager *manager_new(void) {
39 Manager *m;
cc377381 40 int r;
20263082
LP
41
42 m = new0(Manager, 1);
43 if (!m)
44 return NULL;
45
46 m->console_active_fd = -1;
98a77df5 47 m->reserve_vt_fd = -1;
069cfc85 48
20263082 49 m->n_autovts = 6;
98a77df5 50 m->reserve_vt = 6;
eecd1362 51 m->inhibit_delay_max = 5 * USEC_PER_SEC;
beaafb2e 52 m->handle_power_key = HANDLE_POWEROFF;
8e7fd6ad
LP
53 m->handle_suspend_key = HANDLE_SUSPEND;
54 m->handle_hibernate_key = HANDLE_HIBERNATE;
beaafb2e
LP
55 m->handle_lid_switch = HANDLE_SUSPEND;
56 m->lid_switch_ignore_inhibited = true;
20263082 57
23406ce5
LP
58 m->idle_action_usec = 30 * USEC_PER_MINUTE;
59 m->idle_action = HANDLE_IGNORE;
60 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
61
20263082
LP
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
fb6becb4
LP
69 m->user_units = hashmap_new(string_hash_func, string_compare_func);
70 m->session_units = hashmap_new(string_hash_func, string_compare_func);
8c8c4351 71
cc377381 72 m->busnames = set_new(string_hash_func, string_compare_func);
20263082 73
e8b212fe 74 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
1ee306e1 75 !m->user_units || !m->session_units ||
cc377381 76 !m->busnames) {
25d93491
LP
77 manager_free(m);
78 return NULL;
79 }
80
25d93491 81 m->kill_exclude_users = strv_new("root", NULL);
fb6becb4 82 if (!m->kill_exclude_users) {
20263082
LP
83 manager_free(m);
84 return NULL;
85 }
86
87 m->udev = udev_new();
88 if (!m->udev) {
89 manager_free(m);
90 return NULL;
91 }
92
afc6adb5 93 r = sd_event_default(&m->event);
cc377381
LP
94 if (r < 0) {
95 manager_free(m);
96 return NULL;
97 }
98
cde93897
LP
99 sd_event_set_watchdog(m->event, true);
100
20263082
LP
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
fb6becb4
LP
139 hashmap_free(m->user_units);
140 hashmap_free(m->session_units);
8c8c4351 141
cc377381
LP
142 set_free_free(m->busnames);
143
144 sd_event_source_unref(m->idle_action_event_source);
145
146 sd_event_source_unref(m->console_active_event_source);
147 sd_event_source_unref(m->udev_seat_event_source);
148 sd_event_source_unref(m->udev_device_event_source);
149 sd_event_source_unref(m->udev_vcsa_event_source);
150 sd_event_source_unref(m->udev_button_event_source);
20263082
LP
151
152 if (m->console_active_fd >= 0)
153 close_nointr_nofail(m->console_active_fd);
154
30ed21ce
LP
155 if (m->udev_seat_monitor)
156 udev_monitor_unref(m->udev_seat_monitor);
718d006a
DH
157 if (m->udev_device_monitor)
158 udev_monitor_unref(m->udev_device_monitor);
30ed21ce
LP
159 if (m->udev_vcsa_monitor)
160 udev_monitor_unref(m->udev_vcsa_monitor);
069cfc85
LP
161 if (m->udev_button_monitor)
162 udev_monitor_unref(m->udev_button_monitor);
20263082
LP
163
164 if (m->udev)
165 udev_unref(m->udev);
166
cc377381 167 bus_verify_polkit_async_registry_free(m->bus, m->polkit_registry);
20263082 168
cc377381
LP
169 sd_bus_unref(m->bus);
170 sd_event_unref(m->event);
20263082 171
98a77df5
LP
172 if (m->reserve_vt_fd >= 0)
173 close_nointr_nofail(m->reserve_vt_fd);
174
193197e8
LP
175 strv_free(m->kill_only_users);
176 strv_free(m->kill_exclude_users);
177
af9792ac 178 free(m->action_job);
20263082
LP
179 free(m);
180}
181
9588bc32 182static int manager_enumerate_devices(Manager *m) {
20263082
LP
183 struct udev_list_entry *item = NULL, *first = NULL;
184 struct udev_enumerate *e;
14c3baca 185 int r;
20263082
LP
186
187 assert(m);
188
189 /* Loads devices from udev and creates seats for them as
190 * necessary */
191
192 e = udev_enumerate_new(m->udev);
14c3baca
LP
193 if (!e) {
194 r = -ENOMEM;
5eda94dd 195 goto finish;
14c3baca 196 }
20263082 197
2d96536d 198 r = udev_enumerate_add_match_tag(e, "master-of-seat");
14c3baca 199 if (r < 0)
20263082
LP
200 goto finish;
201
14c3baca
LP
202 r = udev_enumerate_scan_devices(e);
203 if (r < 0)
20263082
LP
204 goto finish;
205
206 first = udev_enumerate_get_list_entry(e);
207 udev_list_entry_foreach(item, first) {
208 struct udev_device *d;
209 int k;
210
211 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
14c3baca
LP
212 if (!d) {
213 r = -ENOMEM;
20263082 214 goto finish;
14c3baca 215 }
20263082 216
30ed21ce 217 k = manager_process_seat_device(m, d);
20263082
LP
218 udev_device_unref(d);
219
220 if (k < 0)
221 r = k;
222 }
223
224finish:
225 if (e)
226 udev_enumerate_unref(e);
227
228 return r;
229}
230
9588bc32 231static int manager_enumerate_buttons(Manager *m) {
069cfc85
LP
232 struct udev_list_entry *item = NULL, *first = NULL;
233 struct udev_enumerate *e;
234 int r;
235
236 assert(m);
237
238 /* Loads buttons from udev */
239
beaafb2e 240 if (m->handle_power_key == HANDLE_IGNORE &&
8e7fd6ad
LP
241 m->handle_suspend_key == HANDLE_IGNORE &&
242 m->handle_hibernate_key == HANDLE_IGNORE &&
beaafb2e 243 m->handle_lid_switch == HANDLE_IGNORE)
6de0e0e5
LP
244 return 0;
245
069cfc85
LP
246 e = udev_enumerate_new(m->udev);
247 if (!e) {
248 r = -ENOMEM;
249 goto finish;
250 }
251
252 r = udev_enumerate_add_match_subsystem(e, "input");
253 if (r < 0)
254 goto finish;
255
256 r = udev_enumerate_add_match_tag(e, "power-switch");
257 if (r < 0)
258 goto finish;
259
260 r = udev_enumerate_scan_devices(e);
261 if (r < 0)
262 goto finish;
263
264 first = udev_enumerate_get_list_entry(e);
265 udev_list_entry_foreach(item, first) {
266 struct udev_device *d;
267 int k;
268
269 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
270 if (!d) {
271 r = -ENOMEM;
272 goto finish;
273 }
274
275 k = manager_process_button_device(m, d);
276 udev_device_unref(d);
277
278 if (k < 0)
279 r = k;
280 }
281
282finish:
283 if (e)
284 udev_enumerate_unref(e);
285
286 return r;
287}
288
9588bc32 289static int manager_enumerate_seats(Manager *m) {
9444b1f2 290 _cleanup_closedir_ DIR *d = NULL;
20263082
LP
291 struct dirent *de;
292 int r = 0;
293
294 assert(m);
295
296 /* This loads data about seats stored on disk, but does not
297 * actually create any seats. Removes data of seats that no
298 * longer exist. */
299
300 d = opendir("/run/systemd/seats");
301 if (!d) {
302 if (errno == ENOENT)
303 return 0;
304
305 log_error("Failed to open /run/systemd/seats: %m");
306 return -errno;
307 }
308
9444b1f2 309 FOREACH_DIRENT(de, d, return -errno) {
20263082
LP
310 Seat *s;
311 int k;
312
313 if (!dirent_is_file(de))
314 continue;
315
316 s = hashmap_get(m->seats, de->d_name);
317 if (!s) {
318 unlinkat(dirfd(d), de->d_name, 0);
319 continue;
320 }
321
322 k = seat_load(s);
323 if (k < 0)
324 r = k;
325 }
326
14c3baca
LP
327 return r;
328}
20263082 329
14c3baca 330static int manager_enumerate_linger_users(Manager *m) {
9444b1f2 331 _cleanup_closedir_ DIR *d = NULL;
14c3baca
LP
332 struct dirent *de;
333 int r = 0;
334
9444b1f2
LP
335 assert(m);
336
14c3baca
LP
337 d = opendir("/var/lib/systemd/linger");
338 if (!d) {
339 if (errno == ENOENT)
340 return 0;
341
342 log_error("Failed to open /var/lib/systemd/linger/: %m");
343 return -errno;
344 }
345
9444b1f2 346 FOREACH_DIRENT(de, d, return -errno) {
14c3baca
LP
347 int k;
348
349 if (!dirent_is_file(de))
20263082
LP
350 continue;
351
14c3baca
LP
352 k = manager_add_user_by_name(m, de->d_name, NULL);
353 if (k < 0) {
354 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
355 r = k;
20263082
LP
356 }
357 }
358
20263082
LP
359 return r;
360}
361
9588bc32 362static int manager_enumerate_users(Manager *m) {
9444b1f2 363 _cleanup_closedir_ DIR *d = NULL;
20263082 364 struct dirent *de;
14c3baca 365 int r, k;
20263082
LP
366
367 assert(m);
368
9444b1f2 369 /* Add lingering users */
b3629c7d 370 r = manager_enumerate_linger_users(m);
14c3baca 371
9444b1f2 372 /* Read in user data stored on disk */
20263082
LP
373 d = opendir("/run/systemd/users");
374 if (!d) {
375 if (errno == ENOENT)
376 return 0;
377
378 log_error("Failed to open /run/systemd/users: %m");
379 return -errno;
380 }
381
9444b1f2 382 FOREACH_DIRENT(de, d, return -errno) {
20263082 383 User *u;
20263082
LP
384
385 if (!dirent_is_file(de))
386 continue;
387
9444b1f2 388 k = manager_add_user_by_name(m, de->d_name, &u);
20263082 389 if (k < 0) {
9444b1f2 390 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
20263082 391
9444b1f2 392 r = k;
20263082
LP
393 continue;
394 }
395
9444b1f2
LP
396 user_add_to_gc_queue(u);
397
20263082
LP
398 k = user_load(u);
399 if (k < 0)
400 r = k;
401 }
402
20263082
LP
403 return r;
404}
405
9588bc32 406static int manager_enumerate_sessions(Manager *m) {
9444b1f2
LP
407 _cleanup_closedir_ DIR *d = NULL;
408 struct dirent *de;
20263082
LP
409 int r = 0;
410
9444b1f2
LP
411 assert(m);
412
413 /* Read in session data stored on disk */
414 d = opendir("/run/systemd/sessions");
415 if (!d) {
416 if (errno == ENOENT)
417 return 0;
418
419 log_error("Failed to open /run/systemd/sessions: %m");
420 return -errno;
421 }
422
423 FOREACH_DIRENT(de, d, return -errno) {
424 struct Session *s;
20263082
LP
425 int k;
426
9444b1f2 427 if (!dirent_is_file(de))
14c3baca
LP
428 continue;
429
4b549144
ZJS
430 if (!session_id_valid(de->d_name)) {
431 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
432 r = -EINVAL;
433 continue;
434 }
435
9444b1f2 436 k = manager_add_session(m, de->d_name, &s);
20263082 437 if (k < 0) {
9444b1f2 438 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
20263082 439
20263082
LP
440 r = k;
441 continue;
442 }
443
9444b1f2 444 session_add_to_gc_queue(s);
20263082 445
9444b1f2 446 k = session_load(s);
20263082
LP
447 if (k < 0)
448 r = k;
449 }
450
451 return r;
452}
453
9588bc32 454static int manager_enumerate_inhibitors(Manager *m) {
9444b1f2 455 _cleanup_closedir_ DIR *d = NULL;
20263082
LP
456 struct dirent *de;
457 int r = 0;
458
459 assert(m);
460
9444b1f2 461 d = opendir("/run/systemd/inhibit");
20263082
LP
462 if (!d) {
463 if (errno == ENOENT)
464 return 0;
465
9444b1f2 466 log_error("Failed to open /run/systemd/inhibit: %m");
20263082
LP
467 return -errno;
468 }
469
9444b1f2 470 FOREACH_DIRENT(de, d, return -errno) {
20263082 471 int k;
9444b1f2 472 Inhibitor *i;
20263082
LP
473
474 if (!dirent_is_file(de))
475 continue;
476
9444b1f2
LP
477 k = manager_add_inhibitor(m, de->d_name, &i);
478 if (k < 0) {
479 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
480 r = k;
20263082
LP
481 continue;
482 }
483
9444b1f2 484 k = inhibitor_load(i);
20263082
LP
485 if (k < 0)
486 r = k;
487 }
488
20263082
LP
489 return r;
490}
491
cc377381
LP
492static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
493 Manager *m = userdata;
20263082
LP
494 struct udev_device *d;
495 int r;
496
497 assert(m);
498
30ed21ce 499 d = udev_monitor_receive_device(m->udev_seat_monitor);
20263082
LP
500 if (!d)
501 return -ENOMEM;
502
30ed21ce
LP
503 r = manager_process_seat_device(m, d);
504 udev_device_unref(d);
505
506 return r;
507}
508
cc377381
LP
509static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
510 Manager *m = userdata;
718d006a
DH
511 struct udev_device *d;
512 int r;
513
514 assert(m);
515
516 d = udev_monitor_receive_device(m->udev_device_monitor);
517 if (!d)
518 return -ENOMEM;
519
520 r = manager_process_seat_device(m, d);
521 udev_device_unref(d);
522
523 return r;
524}
525
cc377381
LP
526static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
527 Manager *m = userdata;
30ed21ce
LP
528 struct udev_device *d;
529 int r = 0;
530 const char *name;
531
532 assert(m);
533
534 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
535 if (!d)
536 return -ENOMEM;
537
538 name = udev_device_get_sysname(d);
539
540 /* Whenever a VCSA device is removed try to reallocate our
541 * VTs, to make sure our auto VTs never go away. */
542
543 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
92432fcc 544 r = seat_preallocate_vts(m->seat0);
30ed21ce 545
20263082
LP
546 udev_device_unref(d);
547
548 return r;
549}
550
cc377381
LP
551static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
552 Manager *m = userdata;
069cfc85
LP
553 struct udev_device *d;
554 int r;
555
556 assert(m);
557
558 d = udev_monitor_receive_device(m->udev_button_monitor);
559 if (!d)
560 return -ENOMEM;
561
562 r = manager_process_button_device(m, d);
563 udev_device_unref(d);
564
565 return r;
566}
567
cc377381
LP
568static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
569 Manager *m = userdata;
570
20263082 571 assert(m);
92432fcc 572 assert(m->seat0);
cc377381 573 assert(m->console_active_fd == fd);
20263082 574
92432fcc 575 seat_read_active_vt(m->seat0);
20263082
LP
576
577 return 0;
578}
579
98a77df5
LP
580static int manager_reserve_vt(Manager *m) {
581 _cleanup_free_ char *p = NULL;
582
583 assert(m);
584
585 if (m->reserve_vt <= 0)
586 return 0;
587
588 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
589 return log_oom();
590
591 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
592 if (m->reserve_vt_fd < 0) {
d4d882e5
LP
593
594 /* Don't complain on VT-less systems */
595 if (errno != ENOENT)
596 log_warning("Failed to pin reserved VT: %m");
98a77df5
LP
597 return -errno;
598 }
599
600 return 0;
601}
602
cc377381
LP
603static int manager_connect_bus(Manager *m) {
604 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
605 int r;
31b79c2b 606
cc377381
LP
607 assert(m);
608 assert(!m->bus);
31b79c2b 609
76b54375 610 r = sd_bus_default_system(&m->bus);
cc377381
LP
611 if (r < 0) {
612 log_error("Failed to connect to system bus: %s", strerror(-r));
613 return r;
f8e2fb7b 614 }
31b79c2b 615
cc377381
LP
616 r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
617 if (r < 0) {
618 log_error("Failed to add manager object vtable: %s", strerror(-r));
619 return r;
f8e2fb7b
LP
620 }
621
cc377381
LP
622 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
623 if (r < 0) {
624 log_error("Failed to add seat object vtable: %s", strerror(-r));
625 return r;
069cfc85
LP
626 }
627
cc377381
LP
628 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
629 if (r < 0) {
630 log_error("Failed to add seat enumerator: %s", strerror(-r));
631 return r;
632 }
20263082 633
cc377381
LP
634 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
635 if (r < 0) {
636 log_error("Failed to add session object vtable: %s", strerror(-r));
637 return r;
638 }
20263082 639
cc377381
LP
640 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/session", session_node_enumerator, m);
641 if (r < 0) {
642 log_error("Failed to add session enumerator: %s", strerror(-r));
643 return r;
644 }
20263082 645
cc377381
LP
646 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
647 if (r < 0) {
648 log_error("Failed to add user object vtable: %s", strerror(-r));
649 return r;
20263082
LP
650 }
651
cc377381
LP
652 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/user", user_node_enumerator, m);
653 if (r < 0) {
654 log_error("Failed to add user enumerator: %s", strerror(-r));
655 return r;
20263082
LP
656 }
657
cc377381
LP
658 r = sd_bus_add_match(m->bus,
659 "type='signal',"
660 "sender='org.freedesktop.DBus',"
661 "interface='org.freedesktop.DBus',"
662 "member='NameOwnerChanged',"
663 "path='/org/freedesktop/DBus'",
664 match_name_owner_changed, m);
665 if (r < 0) {
666 log_error("Failed to add match for NameOwnerChanged: %s", strerror(-r));
667 return r;
e8b212fe
DH
668 }
669
cc377381
LP
670 r = sd_bus_add_match(m->bus,
671 "type='signal',"
672 "sender='org.freedesktop.systemd1',"
673 "interface='org.freedesktop.systemd1.Manager',"
674 "member='JobRemoved',"
675 "path='/org/freedesktop/systemd1'",
676 match_job_removed, m);
677 if (r < 0) {
678 log_error("Failed to add match for JobRemoved: %s", strerror(-r));
679 return r;
943aca8e
LP
680 }
681
cc377381
LP
682 r = sd_bus_add_match(m->bus,
683 "type='signal',"
684 "sender='org.freedesktop.systemd1',"
685 "interface='org.freedesktop.systemd1.Manager',"
686 "member='UnitRemoved',"
687 "path='/org/freedesktop/systemd1'",
688 match_unit_removed, m);
689 if (r < 0) {
690 log_error("Failed to add match for UnitRemoved: %s", strerror(-r));
691 return r;
fb6becb4
LP
692 }
693
cc377381
LP
694 r = sd_bus_add_match(m->bus,
695 "type='signal',"
696 "sender='org.freedesktop.systemd1',"
697 "interface='org.freedesktop.DBus.Properties',"
698 "member='PropertiesChanged'",
699 match_properties_changed, m);
700 if (r < 0) {
701 log_error("Failed to add match for PropertiesChanged: %s", strerror(-r));
702 return r;
fb6becb4
LP
703 }
704
cc377381
LP
705 r = sd_bus_add_match(m->bus,
706 "type='signal',"
707 "sender='org.freedesktop.systemd1',"
708 "interface='org.freedesktop.systemd1.Manager',"
709 "member='Reloading',"
710 "path='/org/freedesktop/systemd1'",
711 match_reloading, m);
712 if (r < 0) {
713 log_error("Failed to add match for Reloading: %s", strerror(-r));
714 return r;
6797c324
LP
715 }
716
cc377381 717 r = sd_bus_call_method(
fb6becb4
LP
718 m->bus,
719 "org.freedesktop.systemd1",
720 "/org/freedesktop/systemd1",
721 "org.freedesktop.systemd1.Manager",
722 "Subscribe",
fb6becb4 723 &error,
cc377381 724 NULL, NULL);
fb6becb4 725 if (r < 0) {
cc377381
LP
726 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
727 return r;
20263082
LP
728 }
729
5bb658a1 730 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
cc377381
LP
731 if (r < 0) {
732 log_error("Failed to register name: %s", strerror(-r));
733 return r;
bafd4449
LP
734 }
735
cc377381
LP
736 r = sd_bus_attach_event(m->bus, m->event, 0);
737 if (r < 0) {
738 log_error("Failed to attach bus to event loop: %s", strerror(-r));
739 return r;
20263082
LP
740 }
741
20263082 742 return 0;
20263082
LP
743}
744
745static int manager_connect_console(Manager *m) {
cc377381 746 int r;
20263082
LP
747
748 assert(m);
749 assert(m->console_active_fd < 0);
750
74afee9c
LP
751 /* On certain architectures (S390 and Xen, and containers),
752 /dev/tty0 does not exist, so don't fail if we can't open
753 it. */
cc377381 754 if (access("/dev/tty0", F_OK) < 0)
74afee9c 755 return 0;
74afee9c 756
20263082
LP
757 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
758 if (m->console_active_fd < 0) {
cdc564d2
MS
759
760 /* On some systems the device node /dev/tty0 may exist
761 * even though /sys/class/tty/tty0 does not. */
762 if (errno == ENOENT)
763 return 0;
764
20263082
LP
765 log_error("Failed to open /sys/class/tty/tty0/active: %m");
766 return -errno;
767 }
768
cc377381
LP
769 r = sd_event_add_io(m->event, m->console_active_fd, 0, manager_dispatch_console, m, &m->console_active_event_source);
770 if (r < 0) {
771 log_error("Failed to watch foreground console");
772 return r;
773 }
20263082
LP
774
775 return 0;
776}
777
778static int manager_connect_udev(Manager *m) {
14c3baca 779 int r;
20263082
LP
780
781 assert(m);
30ed21ce 782 assert(!m->udev_seat_monitor);
718d006a 783 assert(!m->udev_device_monitor);
30ed21ce 784 assert(!m->udev_vcsa_monitor);
069cfc85 785 assert(!m->udev_button_monitor);
20263082 786
30ed21ce
LP
787 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
788 if (!m->udev_seat_monitor)
20263082
LP
789 return -ENOMEM;
790
2d96536d 791 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
14c3baca
LP
792 if (r < 0)
793 return r;
20263082 794
30ed21ce 795 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
14c3baca
LP
796 if (r < 0)
797 return r;
20263082 798
cc377381
LP
799 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m, &m->udev_seat_event_source);
800 if (r < 0)
801 return r;
069cfc85 802
718d006a
DH
803 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
804 if (!m->udev_device_monitor)
805 return -ENOMEM;
806
807 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
808 if (r < 0)
809 return r;
810
811 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
812 if (r < 0)
813 return r;
814
815 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
816 if (r < 0)
817 return r;
818
819 r = udev_monitor_enable_receiving(m->udev_device_monitor);
820 if (r < 0)
821 return r;
822
cc377381
LP
823 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m, &m->udev_device_event_source);
824 if (r < 0)
825 return r;
718d006a 826
6de0e0e5 827 /* Don't watch keys if nobody cares */
beaafb2e 828 if (m->handle_power_key != HANDLE_IGNORE ||
8e7fd6ad
LP
829 m->handle_suspend_key != HANDLE_IGNORE ||
830 m->handle_hibernate_key != HANDLE_IGNORE ||
beaafb2e 831 m->handle_lid_switch != HANDLE_IGNORE) {
069cfc85 832
6de0e0e5
LP
833 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
834 if (!m->udev_button_monitor)
835 return -ENOMEM;
069cfc85 836
6de0e0e5
LP
837 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
838 if (r < 0)
839 return r;
069cfc85 840
6de0e0e5
LP
841 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
842 if (r < 0)
843 return r;
069cfc85 844
6de0e0e5
LP
845 r = udev_monitor_enable_receiving(m->udev_button_monitor);
846 if (r < 0)
847 return r;
069cfc85 848
cc377381
LP
849 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m, &m->udev_button_event_source);
850 if (r < 0)
851 return r;
6de0e0e5 852 }
069cfc85 853
976c088a 854 /* Don't bother watching VCSA devices, if nobody cares */
6de0e0e5 855 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
30ed21ce 856
6de0e0e5
LP
857 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
858 if (!m->udev_vcsa_monitor)
859 return -ENOMEM;
30ed21ce 860
6de0e0e5
LP
861 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
862 if (r < 0)
863 return r;
30ed21ce 864
6de0e0e5
LP
865 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
866 if (r < 0)
867 return r;
30ed21ce 868
cc377381
LP
869 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m, &m->udev_vcsa_event_source);
870 if (r < 0)
871 return r;
6de0e0e5 872 }
20263082
LP
873
874 return 0;
875}
876
4a4b033f 877void manager_gc(Manager *m, bool drop_not_started) {
14c3baca
LP
878 Seat *seat;
879 Session *session;
880 User *user;
881
882 assert(m);
883
884 while ((seat = m->seat_gc_queue)) {
71fda00f 885 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
14c3baca
LP
886 seat->in_gc_queue = false;
887
cc377381 888 if (!seat_check_gc(seat, drop_not_started)) {
14c3baca
LP
889 seat_stop(seat);
890 seat_free(seat);
891 }
892 }
893
894 while ((session = m->session_gc_queue)) {
71fda00f 895 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
14c3baca
LP
896 session->in_gc_queue = false;
897
cc377381 898 if (!session_check_gc(session, drop_not_started)) {
14c3baca 899 session_stop(session);
405e0255 900 session_finalize(session);
14c3baca
LP
901 session_free(session);
902 }
903 }
904
905 while ((user = m->user_gc_queue)) {
71fda00f 906 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
14c3baca
LP
907 user->in_gc_queue = false;
908
cc377381 909 if (!user_check_gc(user, drop_not_started)) {
14c3baca 910 user_stop(user);
405e0255 911 user_finalize(user);
14c3baca
LP
912 user_free(user);
913 }
914 }
915}
916
cc377381
LP
917static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
918 Manager *m = userdata;
23406ce5 919 struct dual_timestamp since;
cc377381 920 usec_t n, elapse;
23406ce5 921 int r;
23406ce5
LP
922
923 assert(m);
924
925 if (m->idle_action == HANDLE_IGNORE ||
cc377381
LP
926 m->idle_action_usec <= 0)
927 return 0;
23406ce5 928
23406ce5
LP
929 n = now(CLOCK_MONOTONIC);
930
931 r = manager_get_idle_hint(m, &since);
932 if (r <= 0)
39ccc87c 933 /* Not idle. Let's check if after a timeout it might be idle then. */
cc377381 934 elapse = n + m->idle_action_usec;
23406ce5
LP
935 else {
936 /* Idle! Let's see if it's time to do something, or if
937 * we shall sleep for longer. */
938
939 if (n >= since.monotonic + m->idle_action_usec &&
940 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
941 log_info("System idle. Taking action.");
942
943 manager_handle_action(m, 0, m->idle_action, false, false);
944 m->idle_action_not_before_usec = n;
945 }
946
cc377381 947 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
23406ce5
LP
948 }
949
cc377381 950 if (!m->idle_action_event_source) {
23406ce5 951
cc377381
LP
952 r = sd_event_add_monotonic(m->event, elapse, USEC_PER_SEC*30, manager_dispatch_idle_action, m, &m->idle_action_event_source);
953 if (r < 0) {
954 log_error("Failed to add idle event source: %s", strerror(-r));
955 return r;
23406ce5
LP
956 }
957
718db961 958 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
cc377381
LP
959 if (r < 0) {
960 log_error("Failed to set idle event source priority: %s", strerror(-r));
961 return r;
962 }
963 } else {
964 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
965 if (r < 0) {
966 log_error("Failed to set idle event timer: %s", strerror(-r));
967 return r;
23406ce5 968 }
23406ce5 969
cc377381
LP
970 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
971 if (r < 0) {
972 log_error("Failed to enable idle event timer: %s", strerror(-r));
973 return r;
974 }
23406ce5
LP
975 }
976
977 return 0;
23406ce5 978}
cc377381 979
20263082
LP
980int manager_startup(Manager *m) {
981 int r;
14c3baca
LP
982 Seat *seat;
983 Session *session;
984 User *user;
f8e2fb7b 985 Inhibitor *inhibitor;
14c3baca 986 Iterator i;
20263082
LP
987
988 assert(m);
20263082 989
976c088a
LP
990 /* Connect to console */
991 r = manager_connect_console(m);
20263082
LP
992 if (r < 0)
993 return r;
994
976c088a
LP
995 /* Connect to udev */
996 r = manager_connect_udev(m);
cc377381
LP
997 if (r < 0) {
998 log_error("Failed to create udev watchers: %s", strerror(-r));
20263082 999 return r;
cc377381 1000 }
20263082
LP
1001
1002 /* Connect to the bus */
1003 r = manager_connect_bus(m);
1004 if (r < 0)
1005 return r;
1006
14c3baca 1007 /* Instantiate magic seat 0 */
92432fcc 1008 r = manager_add_seat(m, "seat0", &m->seat0);
cc377381
LP
1009 if (r < 0) {
1010 log_error("Failed to add seat0: %s", strerror(-r));
14c3baca 1011 return r;
cc377381 1012 }
14c3baca 1013
20263082 1014 /* Deserialize state */
042f5988
ZJS
1015 r = manager_enumerate_devices(m);
1016 if (r < 0)
1017 log_warning("Device enumeration failed: %s", strerror(-r));
1018
1019 r = manager_enumerate_seats(m);
1020 if (r < 0)
1021 log_warning("Seat enumeration failed: %s", strerror(-r));
1022
1023 r = manager_enumerate_users(m);
1024 if (r < 0)
1025 log_warning("User enumeration failed: %s", strerror(-r));
1026
1027 r = manager_enumerate_sessions(m);
1028 if (r < 0)
1029 log_warning("Session enumeration failed: %s", strerror(-r));
1030
1031 r = manager_enumerate_inhibitors(m);
1032 if (r < 0)
1033 log_warning("Inhibitor enumeration failed: %s", strerror(-r));
1034
1035 r = manager_enumerate_buttons(m);
1036 if (r < 0)
1037 log_warning("Button enumeration failed: %s", strerror(-r));
20263082 1038
4a4b033f
LP
1039 /* Remove stale objects before we start them */
1040 manager_gc(m, false);
1041
98a77df5
LP
1042 /* Reserve the special reserved VT */
1043 manager_reserve_vt(m);
1044
14c3baca
LP
1045 /* And start everything */
1046 HASHMAP_FOREACH(seat, m->seats, i)
1047 seat_start(seat);
1048
1049 HASHMAP_FOREACH(user, m->users, i)
1050 user_start(user);
1051
1052 HASHMAP_FOREACH(session, m->sessions, i)
1053 session_start(session);
20263082 1054
f8e2fb7b
LP
1055 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1056 inhibitor_start(inhibitor);
1057
cc377381 1058 manager_dispatch_idle_action(NULL, 0, m);
23406ce5 1059
20263082
LP
1060 return 0;
1061}
1062
65b51162
LP
1063static int manager_recheck_buttons(Manager *m) {
1064 Iterator i;
1065 Button *b;
1066 int r = 0;
1067
1068 assert(m);
1069
1070 HASHMAP_FOREACH(b, m->buttons, i) {
1071 int q;
1072
1073 q = button_recheck(b);
1074 if (q > 0)
1075 return 1;
1076 if (q < 0)
1077 r = q;
1078 }
1079
1080 return r;
1081}
1082
20263082 1083int manager_run(Manager *m) {
cc377381
LP
1084 int r;
1085
20263082
LP
1086 assert(m);
1087
1088 for (;;) {
cc377381
LP
1089 usec_t us = (uint64_t) -1;
1090
1091 r = sd_event_get_state(m->event);
1092 if (r < 0)
1093 return r;
1094 if (r == SD_EVENT_FINISHED)
1095 return 0;
20263082 1096
4a4b033f 1097 manager_gc(m, true);
14c3baca 1098
d889a206 1099 if (manager_dispatch_delayed(m) > 0)
eecd1362
LP
1100 continue;
1101
65b51162
LP
1102 if (manager_recheck_buttons(m) > 0)
1103 continue;
1104
84286536 1105 if (m->action_what != 0 && !m->action_job) {
eecd1362
LP
1106 usec_t x, y;
1107
1108 x = now(CLOCK_MONOTONIC);
314b4b0a 1109 y = m->action_timestamp + m->inhibit_delay_max;
eecd1362 1110
cc377381 1111 us = x >= y ? 0 : y - x;
eecd1362
LP
1112 }
1113
cc377381
LP
1114 r = sd_event_run(m->event, us);
1115 if (r < 0)
1116 return r;
20263082
LP
1117 }
1118
1119 return 0;
1120}
1121
193197e8 1122static int manager_parse_config_file(Manager *m) {
db5c0122
LP
1123 static const char fn[] = "/etc/systemd/logind.conf";
1124 _cleanup_fclose_ FILE *f = NULL;
193197e8
LP
1125 int r;
1126
1127 assert(m);
1128
193197e8
LP
1129 f = fopen(fn, "re");
1130 if (!f) {
1131 if (errno == ENOENT)
1132 return 0;
1133
1134 log_warning("Failed to open configuration file %s: %m", fn);
1135 return -errno;
1136 }
1137
db5c0122
LP
1138 r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup,
1139 (void*) logind_gperf_lookup, false, false, m);
193197e8
LP
1140 if (r < 0)
1141 log_warning("Failed to parse configuration file: %s", strerror(-r));
1142
193197e8
LP
1143 return r;
1144}
1145
20263082
LP
1146int main(int argc, char *argv[]) {
1147 Manager *m = NULL;
5eda94dd 1148 int r;
20263082
LP
1149
1150 log_set_target(LOG_TARGET_AUTO);
3eff4208 1151 log_set_facility(LOG_AUTH);
20263082
LP
1152 log_parse_environment();
1153 log_open();
1154
4c12626c
LP
1155 umask(0022);
1156
20263082
LP
1157 if (argc != 1) {
1158 log_error("This program takes no arguments.");
1159 r = -EINVAL;
1160 goto finish;
1161 }
1162
bb27ff66
LP
1163 /* Always create the directories people can create inotify
1164 * watches in. Note that some applications might check for the
ab06eef8 1165 * existence of /run/systemd/seats/ to determine whether
bb27ff66
LP
1166 * logind is available, so please always make sure this check
1167 * stays in. */
1168 mkdir_label("/run/systemd/seats", 0755);
1169 mkdir_label("/run/systemd/users", 0755);
1170 mkdir_label("/run/systemd/sessions", 0755);
1171
20263082
LP
1172 m = manager_new();
1173 if (!m) {
0d0f0c50 1174 r = log_oom();
20263082
LP
1175 goto finish;
1176 }
1177
193197e8
LP
1178 manager_parse_config_file(m);
1179
20263082
LP
1180 r = manager_startup(m);
1181 if (r < 0) {
1182 log_error("Failed to fully start up daemon: %s", strerror(-r));
1183 goto finish;
1184 }
1185
e6960940
LP
1186 log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1187
1188 sd_notify(false,
1189 "READY=1\n"
1190 "STATUS=Processing requests...");
1191
20263082
LP
1192 r = manager_run(m);
1193
e6960940
LP
1194 log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1195
20263082 1196finish:
e6960940
LP
1197 sd_notify(false,
1198 "STATUS=Shutting down...");
1199
20263082
LP
1200 if (m)
1201 manager_free(m);
1202
1203 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1204}