]> git.proxmox.com Git - systemd.git/blame - src/login/logind.c
Imported Upstream version 218
[systemd.git] / src / login / logind.c
CommitLineData
663996b3
MS
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
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
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
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
663996b3
MS
23#include <libudev.h>
24#include <fcntl.h>
25#include <string.h>
26#include <unistd.h>
663996b3
MS
27#include <linux/vt.h>
28#include <sys/timerfd.h>
29
60f067b4 30#include "sd-daemon.h"
663996b3
MS
31#include "strv.h"
32#include "conf-parser.h"
33#include "mkdir.h"
60f067b4
JS
34#include "bus-util.h"
35#include "bus-error.h"
36#include "logind.h"
37#include "udev-util.h"
663996b3
MS
38
39Manager *manager_new(void) {
40 Manager *m;
60f067b4 41 int r;
663996b3
MS
42
43 m = new0(Manager, 1);
44 if (!m)
45 return NULL;
46
47 m->console_active_fd = -1;
663996b3
MS
48 m->reserve_vt_fd = -1;
49
50 m->n_autovts = 6;
51 m->reserve_vt = 6;
60f067b4 52 m->remove_ipc = true;
663996b3
MS
53 m->inhibit_delay_max = 5 * USEC_PER_SEC;
54 m->handle_power_key = HANDLE_POWEROFF;
55 m->handle_suspend_key = HANDLE_SUSPEND;
56 m->handle_hibernate_key = HANDLE_HIBERNATE;
57 m->handle_lid_switch = HANDLE_SUSPEND;
5eef597e 58 m->handle_lid_switch_docked = HANDLE_IGNORE;
663996b3
MS
59 m->lid_switch_ignore_inhibited = true;
60
663996b3
MS
61 m->idle_action_usec = 30 * USEC_PER_MINUTE;
62 m->idle_action = HANDLE_IGNORE;
63 m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
64
60f067b4
JS
65 m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
66
5eef597e
MP
67 m->devices = hashmap_new(&string_hash_ops);
68 m->seats = hashmap_new(&string_hash_ops);
69 m->sessions = hashmap_new(&string_hash_ops);
70 m->users = hashmap_new(NULL);
71 m->inhibitors = hashmap_new(&string_hash_ops);
72 m->buttons = hashmap_new(&string_hash_ops);
663996b3 73
5eef597e
MP
74 m->user_units = hashmap_new(&string_hash_ops);
75 m->session_units = hashmap_new(&string_hash_ops);
663996b3 76
5eef597e 77 m->busnames = set_new(&string_hash_ops);
663996b3 78
14228c0d 79 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
60f067b4
JS
80 !m->user_units || !m->session_units)
81 goto fail;
663996b3 82
663996b3 83 m->kill_exclude_users = strv_new("root", NULL);
60f067b4
JS
84 if (!m->kill_exclude_users)
85 goto fail;
663996b3
MS
86
87 m->udev = udev_new();
60f067b4
JS
88 if (!m->udev)
89 goto fail;
90
91 r = sd_event_default(&m->event);
92 if (r < 0)
93 goto fail;
94
95 sd_event_set_watchdog(m->event, true);
663996b3 96
663996b3 97 return m;
60f067b4
JS
98
99fail:
100 manager_free(m);
101 return NULL;
663996b3
MS
102}
103
104void manager_free(Manager *m) {
105 Session *session;
106 User *u;
107 Device *d;
108 Seat *s;
109 Inhibitor *i;
110 Button *b;
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
126 while ((i = hashmap_first(m->inhibitors)))
127 inhibitor_free(i);
128
129 while ((b = hashmap_first(m->buttons)))
130 button_free(b);
131
132 hashmap_free(m->devices);
133 hashmap_free(m->seats);
134 hashmap_free(m->sessions);
135 hashmap_free(m->users);
136 hashmap_free(m->inhibitors);
137 hashmap_free(m->buttons);
138
14228c0d
MB
139 hashmap_free(m->user_units);
140 hashmap_free(m->session_units);
663996b3 141
60f067b4
JS
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);
151 sd_event_source_unref(m->lid_switch_ignore_event_source);
663996b3 152
60f067b4 153 safe_close(m->console_active_fd);
663996b3
MS
154
155 if (m->udev_seat_monitor)
156 udev_monitor_unref(m->udev_seat_monitor);
14228c0d
MB
157 if (m->udev_device_monitor)
158 udev_monitor_unref(m->udev_device_monitor);
663996b3
MS
159 if (m->udev_vcsa_monitor)
160 udev_monitor_unref(m->udev_vcsa_monitor);
161 if (m->udev_button_monitor)
162 udev_monitor_unref(m->udev_button_monitor);
163
164 if (m->udev)
165 udev_unref(m->udev);
166
5eef597e 167 bus_verify_polkit_async_registry_free(m->polkit_registry);
663996b3 168
60f067b4
JS
169 sd_bus_unref(m->bus);
170 sd_event_unref(m->event);
663996b3 171
60f067b4 172 safe_close(m->reserve_vt_fd);
663996b3 173
663996b3
MS
174 strv_free(m->kill_only_users);
175 strv_free(m->kill_exclude_users);
176
177 free(m->action_job);
663996b3
MS
178 free(m);
179}
180
60f067b4 181static int manager_enumerate_devices(Manager *m) {
663996b3 182 struct udev_list_entry *item = NULL, *first = NULL;
60f067b4 183 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
663996b3
MS
184 int r;
185
186 assert(m);
187
188 /* Loads devices from udev and creates seats for them as
189 * necessary */
190
191 e = udev_enumerate_new(m->udev);
60f067b4
JS
192 if (!e)
193 return -ENOMEM;
663996b3
MS
194
195 r = udev_enumerate_add_match_tag(e, "master-of-seat");
196 if (r < 0)
60f067b4
JS
197 return r;
198
199 r = udev_enumerate_add_match_is_initialized(e);
200 if (r < 0)
201 return r;
663996b3
MS
202
203 r = udev_enumerate_scan_devices(e);
204 if (r < 0)
60f067b4 205 return r;
663996b3
MS
206
207 first = udev_enumerate_get_list_entry(e);
208 udev_list_entry_foreach(item, first) {
60f067b4 209 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
663996b3
MS
210 int k;
211
212 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
60f067b4
JS
213 if (!d)
214 return -ENOMEM;
663996b3
MS
215
216 k = manager_process_seat_device(m, d);
663996b3
MS
217 if (k < 0)
218 r = k;
219 }
220
663996b3
MS
221 return r;
222}
223
60f067b4
JS
224static int manager_enumerate_buttons(Manager *m) {
225 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
663996b3 226 struct udev_list_entry *item = NULL, *first = NULL;
663996b3
MS
227 int r;
228
229 assert(m);
230
231 /* Loads buttons from udev */
232
233 if (m->handle_power_key == HANDLE_IGNORE &&
234 m->handle_suspend_key == HANDLE_IGNORE &&
235 m->handle_hibernate_key == HANDLE_IGNORE &&
5eef597e
MP
236 m->handle_lid_switch == HANDLE_IGNORE &&
237 m->handle_lid_switch_docked == HANDLE_IGNORE)
663996b3
MS
238 return 0;
239
240 e = udev_enumerate_new(m->udev);
60f067b4
JS
241 if (!e)
242 return -ENOMEM;
663996b3
MS
243
244 r = udev_enumerate_add_match_subsystem(e, "input");
245 if (r < 0)
60f067b4 246 return r;
663996b3
MS
247
248 r = udev_enumerate_add_match_tag(e, "power-switch");
249 if (r < 0)
60f067b4
JS
250 return r;
251
252 r = udev_enumerate_add_match_is_initialized(e);
253 if (r < 0)
254 return r;
663996b3
MS
255
256 r = udev_enumerate_scan_devices(e);
257 if (r < 0)
60f067b4 258 return r;
663996b3
MS
259
260 first = udev_enumerate_get_list_entry(e);
261 udev_list_entry_foreach(item, first) {
60f067b4 262 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
663996b3
MS
263 int k;
264
265 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
60f067b4
JS
266 if (!d)
267 return -ENOMEM;
663996b3
MS
268
269 k = manager_process_button_device(m, d);
663996b3
MS
270 if (k < 0)
271 r = k;
272 }
273
663996b3
MS
274 return r;
275}
276
60f067b4 277static int manager_enumerate_seats(Manager *m) {
14228c0d 278 _cleanup_closedir_ DIR *d = NULL;
663996b3
MS
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
f47781d8 293 log_error_errno(errno, "Failed to open /run/systemd/seats: %m");
663996b3
MS
294 return -errno;
295 }
296
14228c0d 297 FOREACH_DIRENT(de, d, return -errno) {
663996b3
MS
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
663996b3
MS
315 return r;
316}
317
318static int manager_enumerate_linger_users(Manager *m) {
14228c0d 319 _cleanup_closedir_ DIR *d = NULL;
663996b3
MS
320 struct dirent *de;
321 int r = 0;
322
14228c0d
MB
323 assert(m);
324
663996b3
MS
325 d = opendir("/var/lib/systemd/linger");
326 if (!d) {
327 if (errno == ENOENT)
328 return 0;
329
f47781d8 330 log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m");
663996b3
MS
331 return -errno;
332 }
333
14228c0d 334 FOREACH_DIRENT(de, d, return -errno) {
663996b3
MS
335 int k;
336
337 if (!dirent_is_file(de))
338 continue;
339
340 k = manager_add_user_by_name(m, de->d_name, NULL);
341 if (k < 0) {
f47781d8 342 log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
663996b3
MS
343 r = k;
344 }
345 }
346
663996b3
MS
347 return r;
348}
349
60f067b4 350static int manager_enumerate_users(Manager *m) {
14228c0d 351 _cleanup_closedir_ DIR *d = NULL;
663996b3
MS
352 struct dirent *de;
353 int r, k;
354
355 assert(m);
356
14228c0d
MB
357 /* Add lingering users */
358 r = manager_enumerate_linger_users(m);
663996b3 359
14228c0d 360 /* Read in user data stored on disk */
663996b3
MS
361 d = opendir("/run/systemd/users");
362 if (!d) {
363 if (errno == ENOENT)
364 return 0;
365
f47781d8 366 log_error_errno(errno, "Failed to open /run/systemd/users: %m");
663996b3
MS
367 return -errno;
368 }
369
14228c0d 370 FOREACH_DIRENT(de, d, return -errno) {
663996b3
MS
371 User *u;
372
373 if (!dirent_is_file(de))
374 continue;
375
14228c0d 376 k = manager_add_user_by_name(m, de->d_name, &u);
663996b3 377 if (k < 0) {
f47781d8 378 log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
663996b3 379
663996b3
MS
380 r = k;
381 continue;
382 }
383
14228c0d 384 user_add_to_gc_queue(u);
663996b3 385
14228c0d 386 k = user_load(u);
663996b3
MS
387 if (k < 0)
388 r = k;
389 }
390
391 return r;
392}
393
60f067b4 394static int manager_enumerate_sessions(Manager *m) {
14228c0d 395 _cleanup_closedir_ DIR *d = NULL;
663996b3
MS
396 struct dirent *de;
397 int r = 0;
398
399 assert(m);
400
14228c0d 401 /* Read in session data stored on disk */
663996b3
MS
402 d = opendir("/run/systemd/sessions");
403 if (!d) {
404 if (errno == ENOENT)
405 return 0;
406
f47781d8 407 log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
663996b3
MS
408 return -errno;
409 }
410
14228c0d 411 FOREACH_DIRENT(de, d, return -errno) {
663996b3
MS
412 struct Session *s;
413 int k;
414
415 if (!dirent_is_file(de))
416 continue;
417
14228c0d
MB
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
424 k = manager_add_session(m, de->d_name, &s);
425 if (k < 0) {
f47781d8 426 log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
14228c0d
MB
427
428 r = k;
663996b3
MS
429 continue;
430 }
431
14228c0d
MB
432 session_add_to_gc_queue(s);
433
663996b3
MS
434 k = session_load(s);
435 if (k < 0)
436 r = k;
437 }
438
663996b3
MS
439 return r;
440}
441
60f067b4 442static int manager_enumerate_inhibitors(Manager *m) {
14228c0d 443 _cleanup_closedir_ DIR *d = NULL;
663996b3
MS
444 struct dirent *de;
445 int r = 0;
446
447 assert(m);
448
449 d = opendir("/run/systemd/inhibit");
450 if (!d) {
451 if (errno == ENOENT)
452 return 0;
453
f47781d8 454 log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
663996b3
MS
455 return -errno;
456 }
457
14228c0d 458 FOREACH_DIRENT(de, d, return -errno) {
663996b3
MS
459 int k;
460 Inhibitor *i;
461
462 if (!dirent_is_file(de))
463 continue;
464
465 k = manager_add_inhibitor(m, de->d_name, &i);
466 if (k < 0) {
f47781d8 467 log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
663996b3
MS
468 r = k;
469 continue;
470 }
471
472 k = inhibitor_load(i);
473 if (k < 0)
474 r = k;
475 }
476
663996b3
MS
477 return r;
478}
479
60f067b4
JS
480static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
481 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
482 Manager *m = userdata;
663996b3
MS
483
484 assert(m);
485
486 d = udev_monitor_receive_device(m->udev_seat_monitor);
487 if (!d)
488 return -ENOMEM;
489
60f067b4
JS
490 manager_process_seat_device(m, d);
491 return 0;
663996b3
MS
492}
493
60f067b4
JS
494static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
495 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
496 Manager *m = userdata;
14228c0d
MB
497
498 assert(m);
499
500 d = udev_monitor_receive_device(m->udev_device_monitor);
501 if (!d)
502 return -ENOMEM;
503
60f067b4
JS
504 manager_process_seat_device(m, d);
505 return 0;
14228c0d
MB
506}
507
60f067b4
JS
508static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
509 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
510 Manager *m = userdata;
663996b3
MS
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"))
60f067b4 525 seat_preallocate_vts(m->seat0);
663996b3 526
60f067b4 527 return 0;
663996b3
MS
528}
529
60f067b4
JS
530static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
531 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
532 Manager *m = userdata;
663996b3
MS
533
534 assert(m);
535
536 d = udev_monitor_receive_device(m->udev_button_monitor);
537 if (!d)
538 return -ENOMEM;
539
60f067b4
JS
540 manager_process_button_device(m, d);
541 return 0;
663996b3
MS
542}
543
60f067b4
JS
544static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
545 Manager *m = userdata;
546
663996b3 547 assert(m);
14228c0d 548 assert(m->seat0);
60f067b4 549 assert(m->console_active_fd == fd);
663996b3 550
14228c0d 551 seat_read_active_vt(m->seat0);
663996b3
MS
552 return 0;
553}
554
663996b3
MS
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) {
568
569 /* Don't complain on VT-less systems */
570 if (errno != ENOENT)
f47781d8 571 log_warning_errno(errno, "Failed to pin reserved VT: %m");
663996b3
MS
572 return -errno;
573 }
574
575 return 0;
576}
577
60f067b4
JS
578static int manager_connect_bus(Manager *m) {
579 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
580 int r;
663996b3 581
60f067b4
JS
582 assert(m);
583 assert(!m->bus);
663996b3 584
60f067b4 585 r = sd_bus_default_system(&m->bus);
f47781d8
MP
586 if (r < 0)
587 return log_error_errno(r, "Failed to connect to system bus: %m");
663996b3 588
60f067b4 589 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
f47781d8
MP
590 if (r < 0)
591 return log_error_errno(r, "Failed to add manager object vtable: %m");
663996b3 592
60f067b4 593 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
f47781d8
MP
594 if (r < 0)
595 return log_error_errno(r, "Failed to add seat object vtable: %m");
663996b3 596
60f067b4 597 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
f47781d8
MP
598 if (r < 0)
599 return log_error_errno(r, "Failed to add seat enumerator: %m");
663996b3 600
60f067b4 601 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
f47781d8
MP
602 if (r < 0)
603 return log_error_errno(r, "Failed to add session object vtable: %m");
663996b3 604
60f067b4 605 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
f47781d8
MP
606 if (r < 0)
607 return log_error_errno(r, "Failed to add session enumerator: %m");
663996b3 608
60f067b4 609 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
f47781d8
MP
610 if (r < 0)
611 return log_error_errno(r, "Failed to add user object vtable: %m");
663996b3 612
60f067b4 613 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
f47781d8
MP
614 if (r < 0)
615 return log_error_errno(r, "Failed to add user enumerator: %m");
663996b3 616
60f067b4
JS
617 r = sd_bus_add_match(m->bus,
618 NULL,
619 "type='signal',"
620 "sender='org.freedesktop.DBus',"
621 "interface='org.freedesktop.DBus',"
622 "member='NameOwnerChanged',"
623 "path='/org/freedesktop/DBus'",
624 match_name_owner_changed, m);
f47781d8
MP
625 if (r < 0)
626 return log_error_errno(r, "Failed to add match for NameOwnerChanged: %m");
14228c0d 627
60f067b4
JS
628 r = sd_bus_add_match(m->bus,
629 NULL,
630 "type='signal',"
631 "sender='org.freedesktop.systemd1',"
632 "interface='org.freedesktop.systemd1.Manager',"
633 "member='JobRemoved',"
634 "path='/org/freedesktop/systemd1'",
635 match_job_removed, m);
f47781d8
MP
636 if (r < 0)
637 return log_error_errno(r, "Failed to add match for JobRemoved: %m");
663996b3 638
60f067b4
JS
639 r = sd_bus_add_match(m->bus,
640 NULL,
641 "type='signal',"
642 "sender='org.freedesktop.systemd1',"
643 "interface='org.freedesktop.systemd1.Manager',"
644 "member='UnitRemoved',"
645 "path='/org/freedesktop/systemd1'",
646 match_unit_removed, m);
f47781d8
MP
647 if (r < 0)
648 return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
14228c0d 649
60f067b4
JS
650 r = sd_bus_add_match(m->bus,
651 NULL,
652 "type='signal',"
653 "sender='org.freedesktop.systemd1',"
654 "interface='org.freedesktop.DBus.Properties',"
655 "member='PropertiesChanged'",
656 match_properties_changed, m);
f47781d8
MP
657 if (r < 0)
658 return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
14228c0d 659
60f067b4
JS
660 r = sd_bus_add_match(m->bus,
661 NULL,
662 "type='signal',"
663 "sender='org.freedesktop.systemd1',"
664 "interface='org.freedesktop.systemd1.Manager',"
665 "member='Reloading',"
666 "path='/org/freedesktop/systemd1'",
667 match_reloading, m);
f47781d8
MP
668 if (r < 0)
669 return log_error_errno(r, "Failed to add match for Reloading: %m");
14228c0d 670
60f067b4 671 r = sd_bus_call_method(
14228c0d
MB
672 m->bus,
673 "org.freedesktop.systemd1",
674 "/org/freedesktop/systemd1",
675 "org.freedesktop.systemd1.Manager",
676 "Subscribe",
14228c0d 677 &error,
60f067b4 678 NULL, NULL);
14228c0d 679 if (r < 0) {
60f067b4
JS
680 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
681 return r;
663996b3
MS
682 }
683
60f067b4 684 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
f47781d8
MP
685 if (r < 0)
686 return log_error_errno(r, "Failed to register name: %m");
663996b3 687
60f067b4 688 r = sd_bus_attach_event(m->bus, m->event, 0);
f47781d8
MP
689 if (r < 0)
690 return log_error_errno(r, "Failed to attach bus to event loop: %m");
663996b3 691
663996b3 692 return 0;
663996b3
MS
693}
694
5eef597e
MP
695static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
696 Manager *m = data;
697 Session *active, *iter;
698
699 /*
700 * We got a VT-switch signal and we have to acknowledge it immediately.
701 * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
702 * old user-space might run multiple sessions on a single VT, *sigh*.
703 * Therefore, we have to iterate all sessions and find one with a vtfd
704 * on the requested VT.
705 * As only VTs with active controllers have VT_PROCESS set, our current
706 * notion of the active VT might be wrong (for instance if the switch
707 * happens while we setup VT_PROCESS). Therefore, read the current VT
708 * first and then use s->active->vtnr as reference. Note that this is
709 * not racy, as no further VT-switch can happen as long as we're in
710 * synchronous VT_PROCESS mode.
711 */
712
713 assert(m->seat0);
714 seat_read_active_vt(m->seat0);
715
716 active = m->seat0->active;
717 if (!active || active->vtnr < 1) {
718 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
719 return 0;
720 }
721
722 if (active->vtfd >= 0) {
723 session_leave_vt(active);
724 } else {
725 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
726 if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
727 session_leave_vt(iter);
728 break;
729 }
730 }
731 }
732
733 return 0;
734}
735
663996b3 736static int manager_connect_console(Manager *m) {
60f067b4 737 int r;
663996b3
MS
738
739 assert(m);
740 assert(m->console_active_fd < 0);
741
742 /* On certain architectures (S390 and Xen, and containers),
743 /dev/tty0 does not exist, so don't fail if we can't open
744 it. */
60f067b4 745 if (access("/dev/tty0", F_OK) < 0)
663996b3 746 return 0;
663996b3
MS
747
748 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
749 if (m->console_active_fd < 0) {
750
751 /* On some systems the device node /dev/tty0 may exist
752 * even though /sys/class/tty/tty0 does not. */
753 if (errno == ENOENT)
754 return 0;
755
f47781d8 756 log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
663996b3
MS
757 return -errno;
758 }
759
60f067b4
JS
760 r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
761 if (r < 0) {
762 log_error("Failed to watch foreground console");
763 return r;
764 }
663996b3 765
5eef597e
MP
766 /*
767 * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
768 * as VT-acquire signal. We ignore any acquire-events (yes, we still
769 * have to provide a valid signal-number for it!) and acknowledge all
770 * release events immediately.
771 */
772
773 if (SIGRTMIN + 1 > SIGRTMAX) {
774 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
775 return -EINVAL;
776 }
777
778 r = ignore_signals(SIGRTMIN + 1, -1);
f47781d8
MP
779 if (r < 0)
780 return log_error_errno(r, "Cannot ignore SIGRTMIN + 1: %m");
5eef597e
MP
781
782 r = sigprocmask_many(SIG_BLOCK, SIGRTMIN, -1);
f47781d8
MP
783 if (r < 0)
784 return log_error_errno(r, "Cannot block SIGRTMIN: %m");
5eef597e
MP
785
786 r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
787 if (r < 0)
788 return r;
789
663996b3
MS
790 return 0;
791}
792
793static int manager_connect_udev(Manager *m) {
794 int r;
663996b3
MS
795
796 assert(m);
797 assert(!m->udev_seat_monitor);
14228c0d 798 assert(!m->udev_device_monitor);
663996b3
MS
799 assert(!m->udev_vcsa_monitor);
800 assert(!m->udev_button_monitor);
801
802 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
803 if (!m->udev_seat_monitor)
804 return -ENOMEM;
805
806 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
807 if (r < 0)
808 return r;
809
810 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
811 if (r < 0)
812 return r;
813
60f067b4
JS
814 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);
815 if (r < 0)
816 return r;
663996b3 817
14228c0d
MB
818 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
819 if (!m->udev_device_monitor)
820 return -ENOMEM;
821
822 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
823 if (r < 0)
824 return r;
825
826 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
827 if (r < 0)
828 return r;
829
830 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
831 if (r < 0)
832 return r;
833
834 r = udev_monitor_enable_receiving(m->udev_device_monitor);
835 if (r < 0)
836 return r;
837
60f067b4
JS
838 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);
839 if (r < 0)
840 return r;
14228c0d 841
663996b3
MS
842 /* Don't watch keys if nobody cares */
843 if (m->handle_power_key != HANDLE_IGNORE ||
844 m->handle_suspend_key != HANDLE_IGNORE ||
845 m->handle_hibernate_key != HANDLE_IGNORE ||
5eef597e
MP
846 m->handle_lid_switch != HANDLE_IGNORE ||
847 m->handle_lid_switch_docked != HANDLE_IGNORE) {
663996b3
MS
848
849 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
850 if (!m->udev_button_monitor)
851 return -ENOMEM;
852
853 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
854 if (r < 0)
855 return r;
856
857 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
858 if (r < 0)
859 return r;
860
861 r = udev_monitor_enable_receiving(m->udev_button_monitor);
862 if (r < 0)
863 return r;
864
60f067b4
JS
865 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);
866 if (r < 0)
867 return r;
663996b3
MS
868 }
869
870 /* Don't bother watching VCSA devices, if nobody cares */
871 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
872
873 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
874 if (!m->udev_vcsa_monitor)
875 return -ENOMEM;
876
877 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
878 if (r < 0)
879 return r;
880
881 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
882 if (r < 0)
883 return r;
884
60f067b4
JS
885 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);
886 if (r < 0)
887 return r;
663996b3
MS
888 }
889
890 return 0;
891}
892
893void manager_gc(Manager *m, bool drop_not_started) {
894 Seat *seat;
895 Session *session;
896 User *user;
897
898 assert(m);
899
900 while ((seat = m->seat_gc_queue)) {
60f067b4 901 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
663996b3
MS
902 seat->in_gc_queue = false;
903
60f067b4
JS
904 if (!seat_check_gc(seat, drop_not_started)) {
905 seat_stop(seat, false);
663996b3
MS
906 seat_free(seat);
907 }
908 }
909
910 while ((session = m->session_gc_queue)) {
60f067b4 911 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
663996b3
MS
912 session->in_gc_queue = false;
913
60f067b4
JS
914 /* First, if we are not closing yet, initiate stopping */
915 if (!session_check_gc(session, drop_not_started) &&
916 session_get_state(session) != SESSION_CLOSING)
917 session_stop(session, false);
918
919 /* Normally, this should make the session busy again,
920 * if it doesn't then let's get rid of it
921 * immediately */
922 if (!session_check_gc(session, drop_not_started)) {
14228c0d 923 session_finalize(session);
663996b3
MS
924 session_free(session);
925 }
926 }
927
928 while ((user = m->user_gc_queue)) {
60f067b4 929 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
663996b3
MS
930 user->in_gc_queue = false;
931
60f067b4
JS
932 /* First step: queue stop jobs */
933 if (!user_check_gc(user, drop_not_started))
934 user_stop(user, false);
935
936 /* Second step: finalize user */
937 if (!user_check_gc(user, drop_not_started)) {
14228c0d 938 user_finalize(user);
663996b3
MS
939 user_free(user);
940 }
941 }
942}
943
60f067b4
JS
944static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
945 Manager *m = userdata;
663996b3 946 struct dual_timestamp since;
60f067b4 947 usec_t n, elapse;
663996b3 948 int r;
663996b3
MS
949
950 assert(m);
951
952 if (m->idle_action == HANDLE_IGNORE ||
60f067b4
JS
953 m->idle_action_usec <= 0)
954 return 0;
663996b3
MS
955
956 n = now(CLOCK_MONOTONIC);
957
958 r = manager_get_idle_hint(m, &since);
959 if (r <= 0)
960 /* Not idle. Let's check if after a timeout it might be idle then. */
60f067b4 961 elapse = n + m->idle_action_usec;
663996b3
MS
962 else {
963 /* Idle! Let's see if it's time to do something, or if
964 * we shall sleep for longer. */
965
966 if (n >= since.monotonic + m->idle_action_usec &&
967 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
968 log_info("System idle. Taking action.");
969
970 manager_handle_action(m, 0, m->idle_action, false, false);
971 m->idle_action_not_before_usec = n;
972 }
973
60f067b4 974 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
663996b3
MS
975 }
976
60f067b4
JS
977 if (!m->idle_action_event_source) {
978
979 r = sd_event_add_time(
980 m->event,
981 &m->idle_action_event_source,
982 CLOCK_MONOTONIC,
983 elapse, USEC_PER_SEC*30,
984 manager_dispatch_idle_action, m);
f47781d8
MP
985 if (r < 0)
986 return log_error_errno(r, "Failed to add idle event source: %m");
663996b3 987
60f067b4 988 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
f47781d8
MP
989 if (r < 0)
990 return log_error_errno(r, "Failed to set idle event source priority: %m");
60f067b4
JS
991 } else {
992 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
f47781d8
MP
993 if (r < 0)
994 return log_error_errno(r, "Failed to set idle event timer: %m");
663996b3 995
60f067b4 996 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
f47781d8
MP
997 if (r < 0)
998 return log_error_errno(r, "Failed to enable idle event timer: %m");
663996b3
MS
999 }
1000
1001 return 0;
663996b3 1002}
60f067b4 1003
663996b3
MS
1004int manager_startup(Manager *m) {
1005 int r;
1006 Seat *seat;
1007 Session *session;
1008 User *user;
60f067b4 1009 Button *button;
663996b3
MS
1010 Inhibitor *inhibitor;
1011 Iterator i;
1012
1013 assert(m);
663996b3
MS
1014
1015 /* Connect to console */
1016 r = manager_connect_console(m);
1017 if (r < 0)
1018 return r;
1019
1020 /* Connect to udev */
1021 r = manager_connect_udev(m);
f47781d8
MP
1022 if (r < 0)
1023 return log_error_errno(r, "Failed to create udev watchers: %m");
663996b3
MS
1024
1025 /* Connect to the bus */
1026 r = manager_connect_bus(m);
1027 if (r < 0)
1028 return r;
1029
1030 /* Instantiate magic seat 0 */
14228c0d 1031 r = manager_add_seat(m, "seat0", &m->seat0);
f47781d8
MP
1032 if (r < 0)
1033 return log_error_errno(r, "Failed to add seat0: %m");
60f067b4
JS
1034
1035 r = manager_set_lid_switch_ignore(m, 0 + IGNORE_LID_SWITCH_STARTUP_USEC);
1036 if (r < 0)
f47781d8 1037 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
663996b3
MS
1038
1039 /* Deserialize state */
14228c0d
MB
1040 r = manager_enumerate_devices(m);
1041 if (r < 0)
f47781d8 1042 log_warning_errno(r, "Device enumeration failed: %m");
14228c0d
MB
1043
1044 r = manager_enumerate_seats(m);
1045 if (r < 0)
f47781d8 1046 log_warning_errno(r, "Seat enumeration failed: %m");
14228c0d
MB
1047
1048 r = manager_enumerate_users(m);
1049 if (r < 0)
f47781d8 1050 log_warning_errno(r, "User enumeration failed: %m");
14228c0d
MB
1051
1052 r = manager_enumerate_sessions(m);
1053 if (r < 0)
f47781d8 1054 log_warning_errno(r, "Session enumeration failed: %m");
14228c0d
MB
1055
1056 r = manager_enumerate_inhibitors(m);
1057 if (r < 0)
f47781d8 1058 log_warning_errno(r, "Inhibitor enumeration failed: %m");
14228c0d
MB
1059
1060 r = manager_enumerate_buttons(m);
1061 if (r < 0)
f47781d8 1062 log_warning_errno(r, "Button enumeration failed: %m");
663996b3
MS
1063
1064 /* Remove stale objects before we start them */
1065 manager_gc(m, false);
1066
1067 /* Reserve the special reserved VT */
1068 manager_reserve_vt(m);
1069
1070 /* And start everything */
1071 HASHMAP_FOREACH(seat, m->seats, i)
1072 seat_start(seat);
1073
1074 HASHMAP_FOREACH(user, m->users, i)
1075 user_start(user);
1076
1077 HASHMAP_FOREACH(session, m->sessions, i)
1078 session_start(session);
1079
1080 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1081 inhibitor_start(inhibitor);
1082
60f067b4
JS
1083 HASHMAP_FOREACH(button, m->buttons, i)
1084 button_check_switches(button);
663996b3 1085
60f067b4 1086 manager_dispatch_idle_action(NULL, 0, m);
663996b3 1087
60f067b4 1088 return 0;
663996b3
MS
1089}
1090
1091int manager_run(Manager *m) {
60f067b4
JS
1092 int r;
1093
663996b3
MS
1094 assert(m);
1095
1096 for (;;) {
60f067b4
JS
1097 usec_t us = (uint64_t) -1;
1098
1099 r = sd_event_get_state(m->event);
1100 if (r < 0)
1101 return r;
1102 if (r == SD_EVENT_FINISHED)
1103 return 0;
663996b3
MS
1104
1105 manager_gc(m, true);
1106
1107 if (manager_dispatch_delayed(m) > 0)
1108 continue;
1109
663996b3
MS
1110 if (m->action_what != 0 && !m->action_job) {
1111 usec_t x, y;
1112
1113 x = now(CLOCK_MONOTONIC);
1114 y = m->action_timestamp + m->inhibit_delay_max;
1115
60f067b4 1116 us = x >= y ? 0 : y - x;
663996b3
MS
1117 }
1118
60f067b4
JS
1119 r = sd_event_run(m->event, us);
1120 if (r < 0)
1121 return r;
663996b3 1122 }
663996b3
MS
1123}
1124
1125static int manager_parse_config_file(Manager *m) {
663996b3
MS
1126 assert(m);
1127
f47781d8
MP
1128 return config_parse_many("/etc/systemd/logind.conf",
1129 CONF_DIRS_NULSTR("systemd/logind.conf"),
1130 "Login\0",
1131 config_item_perf_lookup, logind_gperf_lookup,
1132 false, m);
663996b3
MS
1133}
1134
1135int main(int argc, char *argv[]) {
1136 Manager *m = NULL;
1137 int r;
1138
1139 log_set_target(LOG_TARGET_AUTO);
1140 log_set_facility(LOG_AUTH);
1141 log_parse_environment();
1142 log_open();
1143
1144 umask(0022);
1145
1146 if (argc != 1) {
1147 log_error("This program takes no arguments.");
1148 r = -EINVAL;
1149 goto finish;
1150 }
1151
1152 /* Always create the directories people can create inotify
1153 * watches in. Note that some applications might check for the
1154 * existence of /run/systemd/seats/ to determine whether
1155 * logind is available, so please always make sure this check
1156 * stays in. */
1157 mkdir_label("/run/systemd/seats", 0755);
1158 mkdir_label("/run/systemd/users", 0755);
1159 mkdir_label("/run/systemd/sessions", 0755);
1160
1161 m = manager_new();
1162 if (!m) {
1163 r = log_oom();
1164 goto finish;
1165 }
1166
1167 manager_parse_config_file(m);
1168
1169 r = manager_startup(m);
1170 if (r < 0) {
f47781d8 1171 log_error_errno(r, "Failed to fully start up daemon: %m");
663996b3
MS
1172 goto finish;
1173 }
1174
60f067b4 1175 log_debug("systemd-logind running as pid "PID_FMT, getpid());
663996b3
MS
1176
1177 sd_notify(false,
1178 "READY=1\n"
1179 "STATUS=Processing requests...");
1180
1181 r = manager_run(m);
1182
60f067b4 1183 log_debug("systemd-logind stopped as pid "PID_FMT, getpid());
663996b3
MS
1184
1185finish:
1186 sd_notify(false,
5eef597e 1187 "STOPPING=1\n"
663996b3
MS
1188 "STATUS=Shutting down...");
1189
1190 if (m)
1191 manager_free(m);
1192
1193 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1194}