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