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