]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind.c
treewide: use log_*_errno whenever %m is in the format string
[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 57 m->handle_lid_switch = HANDLE_SUSPEND;
3c56cab4 58 m->handle_lid_switch_docked = HANDLE_IGNORE;
beaafb2e 59 m->lid_switch_ignore_inhibited = true;
20263082 60
23406ce5
LP
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
1c231f56
LP
65 m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
66
d5099efc
MS
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);
f8e2fb7b 73
d5099efc
MS
74 m->user_units = hashmap_new(&string_hash_ops);
75 m->session_units = hashmap_new(&string_hash_ops);
8c8c4351 76
d5099efc 77 m->busnames = set_new(&string_hash_ops);
20263082 78
e8b212fe 79 if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->busnames ||
ed4ba7e4
LP
80 !m->user_units || !m->session_units)
81 goto fail;
25d93491 82
25d93491 83 m->kill_exclude_users = strv_new("root", NULL);
ed4ba7e4
LP
84 if (!m->kill_exclude_users)
85 goto fail;
20263082
LP
86
87 m->udev = udev_new();
ed4ba7e4
LP
88 if (!m->udev)
89 goto fail;
20263082 90
afc6adb5 91 r = sd_event_default(&m->event);
ed4ba7e4
LP
92 if (r < 0)
93 goto fail;
cc377381 94
cde93897
LP
95 sd_event_set_watchdog(m->event, true);
96
20263082 97 return m;
ed4ba7e4
LP
98
99fail:
100 manager_free(m);
101 return NULL;
20263082
LP
102}
103
104void manager_free(Manager *m) {
105 Session *session;
106 User *u;
107 Device *d;
108 Seat *s;
f8e2fb7b 109 Inhibitor *i;
069cfc85 110 Button *b;
20263082
LP
111
112 assert(m);
113
114 while ((session = hashmap_first(m->sessions)))
115 session_free(session);
116
117 while ((u = hashmap_first(m->users)))
118 user_free(u);
119
120 while ((d = hashmap_first(m->devices)))
121 device_free(d);
122
123 while ((s = hashmap_first(m->seats)))
124 seat_free(s);
125
f8e2fb7b
LP
126 while ((i = hashmap_first(m->inhibitors)))
127 inhibitor_free(i);
128
069cfc85
LP
129 while ((b = hashmap_first(m->buttons)))
130 button_free(b);
131
20263082
LP
132 hashmap_free(m->devices);
133 hashmap_free(m->seats);
f8e2fb7b
LP
134 hashmap_free(m->sessions);
135 hashmap_free(m->users);
136 hashmap_free(m->inhibitors);
069cfc85 137 hashmap_free(m->buttons);
f8e2fb7b 138
fb6becb4
LP
139 hashmap_free(m->user_units);
140 hashmap_free(m->session_units);
8c8c4351 141
cc377381
LP
142 set_free_free(m->busnames);
143
144 sd_event_source_unref(m->idle_action_event_source);
145
146 sd_event_source_unref(m->console_active_event_source);
147 sd_event_source_unref(m->udev_seat_event_source);
148 sd_event_source_unref(m->udev_device_event_source);
149 sd_event_source_unref(m->udev_vcsa_event_source);
150 sd_event_source_unref(m->udev_button_event_source);
f9cd6be1 151 sd_event_source_unref(m->lid_switch_ignore_event_source);
20263082 152
03e334a1 153 safe_close(m->console_active_fd);
20263082 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
36e34057 167 bus_verify_polkit_async_registry_free(m->polkit_registry);
20263082 168
cc377381
LP
169 sd_bus_unref(m->bus);
170 sd_event_unref(m->event);
20263082 171
03e334a1 172 safe_close(m->reserve_vt_fd);
98a77df5 173
193197e8
LP
174 strv_free(m->kill_only_users);
175 strv_free(m->kill_exclude_users);
176
af9792ac 177 free(m->action_job);
20263082
LP
178 free(m);
179}
180
9588bc32 181static int manager_enumerate_devices(Manager *m) {
20263082 182 struct udev_list_entry *item = NULL, *first = NULL;
bf5332d2 183 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
14c3baca 184 int r;
20263082
LP
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);
bf5332d2
LP
192 if (!e)
193 return -ENOMEM;
20263082 194
2d96536d 195 r = udev_enumerate_add_match_tag(e, "master-of-seat");
14c3baca 196 if (r < 0)
bf5332d2 197 return r;
20263082 198
e1202047
LP
199 r = udev_enumerate_add_match_is_initialized(e);
200 if (r < 0)
201 return r;
202
14c3baca
LP
203 r = udev_enumerate_scan_devices(e);
204 if (r < 0)
bf5332d2 205 return r;
20263082
LP
206
207 first = udev_enumerate_get_list_entry(e);
208 udev_list_entry_foreach(item, first) {
bf5332d2 209 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
20263082
LP
210 int k;
211
212 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
bf5332d2
LP
213 if (!d)
214 return -ENOMEM;
20263082 215
bf5332d2 216 k = manager_process_seat_device(m, d);
20263082
LP
217 if (k < 0)
218 r = k;
219 }
220
20263082
LP
221 return r;
222}
223
9588bc32 224static int manager_enumerate_buttons(Manager *m) {
bf5332d2 225 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
069cfc85 226 struct udev_list_entry *item = NULL, *first = NULL;
069cfc85
LP
227 int r;
228
229 assert(m);
230
231 /* Loads buttons from udev */
232
beaafb2e 233 if (m->handle_power_key == HANDLE_IGNORE &&
8e7fd6ad
LP
234 m->handle_suspend_key == HANDLE_IGNORE &&
235 m->handle_hibernate_key == HANDLE_IGNORE &&
3c56cab4
BW
236 m->handle_lid_switch == HANDLE_IGNORE &&
237 m->handle_lid_switch_docked == 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
56f64d95 293 log_error_errno(errno, "Failed to open /run/systemd/seats: %m");
20263082
LP
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
56f64d95 330 log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m");
14c3baca
LP
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) {
da927ba9 342 log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
14c3baca 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
56f64d95 366 log_error_errno(errno, "Failed to open /run/systemd/users: %m");
20263082
LP
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) {
da927ba9 378 log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
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
56f64d95 407 log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
9444b1f2
LP
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) {
da927ba9 426 log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
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
56f64d95 454 log_error_errno(errno, "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) {
da927ba9 467 log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
9444b1f2 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)
56f64d95 571 log_warning_errno(errno, "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);
f647962d
MS
586 if (r < 0)
587 return log_error_errno(r, "Failed to connect to system bus: %m");
31b79c2b 588
19befb2d 589 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
f647962d
MS
590 if (r < 0)
591 return log_error_errno(r, "Failed to add manager object vtable: %m");
f8e2fb7b 592
19befb2d 593 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
f647962d
MS
594 if (r < 0)
595 return log_error_errno(r, "Failed to add seat object vtable: %m");
069cfc85 596
19befb2d 597 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
f647962d
MS
598 if (r < 0)
599 return log_error_errno(r, "Failed to add seat enumerator: %m");
20263082 600
19befb2d 601 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
f647962d
MS
602 if (r < 0)
603 return log_error_errno(r, "Failed to add session object vtable: %m");
20263082 604
19befb2d 605 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
f647962d
MS
606 if (r < 0)
607 return log_error_errno(r, "Failed to add session enumerator: %m");
20263082 608
19befb2d 609 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
f647962d
MS
610 if (r < 0)
611 return log_error_errno(r, "Failed to add user object vtable: %m");
20263082 612
19befb2d 613 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
f647962d
MS
614 if (r < 0)
615 return log_error_errno(r, "Failed to add user enumerator: %m");
20263082 616
cc377381 617 r = sd_bus_add_match(m->bus,
19befb2d 618 NULL,
cc377381
LP
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);
f647962d
MS
625 if (r < 0)
626 return log_error_errno(r, "Failed to add match for NameOwnerChanged: %m");
e8b212fe 627
cc377381 628 r = sd_bus_add_match(m->bus,
19befb2d 629 NULL,
cc377381
LP
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);
f647962d
MS
636 if (r < 0)
637 return log_error_errno(r, "Failed to add match for JobRemoved: %m");
943aca8e 638
cc377381 639 r = sd_bus_add_match(m->bus,
19befb2d 640 NULL,
cc377381
LP
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);
f647962d
MS
647 if (r < 0)
648 return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
fb6becb4 649
cc377381 650 r = sd_bus_add_match(m->bus,
19befb2d 651 NULL,
cc377381
LP
652 "type='signal',"
653 "sender='org.freedesktop.systemd1',"
654 "interface='org.freedesktop.DBus.Properties',"
655 "member='PropertiesChanged'",
656 match_properties_changed, m);
f647962d
MS
657 if (r < 0)
658 return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
fb6becb4 659
cc377381 660 r = sd_bus_add_match(m->bus,
19befb2d 661 NULL,
cc377381
LP
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);
f647962d
MS
668 if (r < 0)
669 return log_error_errno(r, "Failed to add match for Reloading: %m");
6797c324 670
cc377381 671 r = sd_bus_call_method(
fb6becb4
LP
672 m->bus,
673 "org.freedesktop.systemd1",
674 "/org/freedesktop/systemd1",
675 "org.freedesktop.systemd1.Manager",
676 "Subscribe",
fb6becb4 677 &error,
cc377381 678 NULL, NULL);
fb6becb4 679 if (r < 0) {
cc377381
LP
680 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
681 return r;
20263082
LP
682 }
683
5bb658a1 684 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
f647962d
MS
685 if (r < 0)
686 return log_error_errno(r, "Failed to register name: %m");
bafd4449 687
cc377381 688 r = sd_bus_attach_event(m->bus, m->event, 0);
f647962d
MS
689 if (r < 0)
690 return log_error_errno(r, "Failed to attach bus to event loop: %m");
20263082 691
20263082 692 return 0;
20263082
LP
693}
694
92683ad2
DH
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) {
2ec3ff66 723 session_leave_vt(active);
92683ad2
DH
724 } else {
725 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
726 if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
2ec3ff66 727 session_leave_vt(iter);
92683ad2
DH
728 break;
729 }
730 }
731 }
732
733 return 0;
734}
735
20263082 736static int manager_connect_console(Manager *m) {
cc377381 737 int r;
20263082
LP
738
739 assert(m);
740 assert(m->console_active_fd < 0);
741
74afee9c
LP
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. */
cc377381 745 if (access("/dev/tty0", F_OK) < 0)
74afee9c 746 return 0;
74afee9c 747
20263082
LP
748 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
749 if (m->console_active_fd < 0) {
cdc564d2
MS
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
56f64d95 756 log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
20263082
LP
757 return -errno;
758 }
759
151b9b96 760 r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
cc377381
LP
761 if (r < 0) {
762 log_error("Failed to watch foreground console");
763 return r;
764 }
20263082 765
92683ad2
DH
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);
f647962d
MS
779 if (r < 0)
780 return log_error_errno(r, "Cannot ignore SIGRTMIN + 1: %m");
92683ad2
DH
781
782 r = sigprocmask_many(SIG_BLOCK, SIGRTMIN, -1);
f647962d
MS
783 if (r < 0)
784 return log_error_errno(r, "Cannot block SIGRTMIN: %m");
92683ad2
DH
785
786 r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
787 if (r < 0)
788 return r;
789
20263082
LP
790 return 0;
791}
792
793static int manager_connect_udev(Manager *m) {
14c3baca 794 int r;
20263082
LP
795
796 assert(m);
30ed21ce 797 assert(!m->udev_seat_monitor);
718d006a 798 assert(!m->udev_device_monitor);
30ed21ce 799 assert(!m->udev_vcsa_monitor);
069cfc85 800 assert(!m->udev_button_monitor);
20263082 801
30ed21ce
LP
802 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
803 if (!m->udev_seat_monitor)
20263082
LP
804 return -ENOMEM;
805
2d96536d 806 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
14c3baca
LP
807 if (r < 0)
808 return r;
20263082 809
30ed21ce 810 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
14c3baca
LP
811 if (r < 0)
812 return r;
20263082 813
151b9b96 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);
cc377381
LP
815 if (r < 0)
816 return r;
069cfc85 817
718d006a
DH
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
151b9b96 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);
cc377381
LP
839 if (r < 0)
840 return r;
718d006a 841
6de0e0e5 842 /* Don't watch keys if nobody cares */
beaafb2e 843 if (m->handle_power_key != HANDLE_IGNORE ||
8e7fd6ad
LP
844 m->handle_suspend_key != HANDLE_IGNORE ||
845 m->handle_hibernate_key != HANDLE_IGNORE ||
3c56cab4
BW
846 m->handle_lid_switch != HANDLE_IGNORE ||
847 m->handle_lid_switch_docked != HANDLE_IGNORE) {
069cfc85 848
6de0e0e5
LP
849 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
850 if (!m->udev_button_monitor)
851 return -ENOMEM;
069cfc85 852
6de0e0e5
LP
853 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
854 if (r < 0)
855 return r;
069cfc85 856
6de0e0e5
LP
857 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
858 if (r < 0)
859 return r;
069cfc85 860
6de0e0e5
LP
861 r = udev_monitor_enable_receiving(m->udev_button_monitor);
862 if (r < 0)
863 return r;
069cfc85 864
151b9b96 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);
cc377381
LP
866 if (r < 0)
867 return r;
6de0e0e5 868 }
069cfc85 869
976c088a 870 /* Don't bother watching VCSA devices, if nobody cares */
6de0e0e5 871 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
30ed21ce 872
6de0e0e5
LP
873 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
874 if (!m->udev_vcsa_monitor)
875 return -ENOMEM;
30ed21ce 876
6de0e0e5
LP
877 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
878 if (r < 0)
879 return r;
30ed21ce 880
6de0e0e5
LP
881 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
882 if (r < 0)
883 return r;
30ed21ce 884
151b9b96 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);
cc377381
LP
886 if (r < 0)
887 return r;
6de0e0e5 888 }
20263082
LP
889
890 return 0;
891}
892
4a4b033f 893void manager_gc(Manager *m, bool drop_not_started) {
14c3baca
LP
894 Seat *seat;
895 Session *session;
896 User *user;
897
898 assert(m);
899
900 while ((seat = m->seat_gc_queue)) {
71fda00f 901 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
14c3baca
LP
902 seat->in_gc_queue = false;
903
cc377381 904 if (!seat_check_gc(seat, drop_not_started)) {
9bb69af4 905 seat_stop(seat, false);
14c3baca
LP
906 seat_free(seat);
907 }
908 }
909
910 while ((session = m->session_gc_queue)) {
71fda00f 911 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
14c3baca
LP
912 session->in_gc_queue = false;
913
5f41d1f1
LP
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)
9bb69af4 917 session_stop(session, false);
5f41d1f1
LP
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)) {
405e0255 923 session_finalize(session);
14c3baca
LP
924 session_free(session);
925 }
926 }
927
928 while ((user = m->user_gc_queue)) {
71fda00f 929 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
14c3baca
LP
930 user->in_gc_queue = false;
931
b58b227a
DH
932 /* First step: queue stop jobs */
933 if (!user_check_gc(user, drop_not_started))
9bb69af4 934 user_stop(user, false);
5f41d1f1 935
b58b227a 936 /* Second step: finalize user */
5f41d1f1 937 if (!user_check_gc(user, drop_not_started)) {
405e0255 938 user_finalize(user);
14c3baca
LP
939 user_free(user);
940 }
941 }
942}
943
cc377381
LP
944static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
945 Manager *m = userdata;
23406ce5 946 struct dual_timestamp since;
cc377381 947 usec_t n, elapse;
23406ce5 948 int r;
23406ce5
LP
949
950 assert(m);
951
952 if (m->idle_action == HANDLE_IGNORE ||
cc377381
LP
953 m->idle_action_usec <= 0)
954 return 0;
23406ce5 955
23406ce5
LP
956 n = now(CLOCK_MONOTONIC);
957
958 r = manager_get_idle_hint(m, &since);
959 if (r <= 0)
39ccc87c 960 /* Not idle. Let's check if after a timeout it might be idle then. */
cc377381 961 elapse = n + m->idle_action_usec;
23406ce5
LP
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
cc377381 974 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
23406ce5
LP
975 }
976
cc377381 977 if (!m->idle_action_event_source) {
23406ce5 978
6a0f1f6d
LP
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);
f647962d
MS
985 if (r < 0)
986 return log_error_errno(r, "Failed to add idle event source: %m");
23406ce5 987
718db961 988 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
f647962d
MS
989 if (r < 0)
990 return log_error_errno(r, "Failed to set idle event source priority: %m");
cc377381
LP
991 } else {
992 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
f647962d
MS
993 if (r < 0)
994 return log_error_errno(r, "Failed to set idle event timer: %m");
23406ce5 995
cc377381 996 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
f647962d
MS
997 if (r < 0)
998 return log_error_errno(r, "Failed to enable idle event timer: %m");
23406ce5
LP
999 }
1000
1001 return 0;
23406ce5 1002}
cc377381 1003
20263082
LP
1004int manager_startup(Manager *m) {
1005 int r;
14c3baca
LP
1006 Seat *seat;
1007 Session *session;
1008 User *user;
ed4ba7e4 1009 Button *button;
f8e2fb7b 1010 Inhibitor *inhibitor;
14c3baca 1011 Iterator i;
20263082
LP
1012
1013 assert(m);
20263082 1014
976c088a
LP
1015 /* Connect to console */
1016 r = manager_connect_console(m);
20263082
LP
1017 if (r < 0)
1018 return r;
1019
976c088a
LP
1020 /* Connect to udev */
1021 r = manager_connect_udev(m);
f647962d
MS
1022 if (r < 0)
1023 return log_error_errno(r, "Failed to create udev watchers: %m");
20263082
LP
1024
1025 /* Connect to the bus */
1026 r = manager_connect_bus(m);
1027 if (r < 0)
1028 return r;
1029
14c3baca 1030 /* Instantiate magic seat 0 */
92432fcc 1031 r = manager_add_seat(m, "seat0", &m->seat0);
f647962d
MS
1032 if (r < 0)
1033 return log_error_errno(r, "Failed to add seat0: %m");
14c3baca 1034
f9cd6be1
LP
1035 r = manager_set_lid_switch_ignore(m, 0 + IGNORE_LID_SWITCH_STARTUP_USEC);
1036 if (r < 0)
da927ba9 1037 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
f9cd6be1 1038
20263082 1039 /* Deserialize state */
042f5988
ZJS
1040 r = manager_enumerate_devices(m);
1041 if (r < 0)
da927ba9 1042 log_warning_errno(r, "Device enumeration failed: %m");
042f5988
ZJS
1043
1044 r = manager_enumerate_seats(m);
1045 if (r < 0)
da927ba9 1046 log_warning_errno(r, "Seat enumeration failed: %m");
042f5988
ZJS
1047
1048 r = manager_enumerate_users(m);
1049 if (r < 0)
da927ba9 1050 log_warning_errno(r, "User enumeration failed: %m");
042f5988
ZJS
1051
1052 r = manager_enumerate_sessions(m);
1053 if (r < 0)
da927ba9 1054 log_warning_errno(r, "Session enumeration failed: %m");
042f5988
ZJS
1055
1056 r = manager_enumerate_inhibitors(m);
1057 if (r < 0)
da927ba9 1058 log_warning_errno(r, "Inhibitor enumeration failed: %m");
042f5988
ZJS
1059
1060 r = manager_enumerate_buttons(m);
1061 if (r < 0)
da927ba9 1062 log_warning_errno(r, "Button enumeration failed: %m");
20263082 1063
4a4b033f
LP
1064 /* Remove stale objects before we start them */
1065 manager_gc(m, false);
1066
98a77df5
LP
1067 /* Reserve the special reserved VT */
1068 manager_reserve_vt(m);
1069
14c3baca
LP
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);
20263082 1079
f8e2fb7b
LP
1080 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1081 inhibitor_start(inhibitor);
1082
ed4ba7e4 1083 HASHMAP_FOREACH(button, m->buttons, i)
2d62c530 1084 button_check_switches(button);
ed4ba7e4 1085
cc377381 1086 manager_dispatch_idle_action(NULL, 0, m);
23406ce5 1087
20263082
LP
1088 return 0;
1089}
1090
1091int manager_run(Manager *m) {
cc377381
LP
1092 int r;
1093
20263082
LP
1094 assert(m);
1095
1096 for (;;) {
cc377381
LP
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;
20263082 1104
4a4b033f 1105 manager_gc(m, true);
14c3baca 1106
d889a206 1107 if (manager_dispatch_delayed(m) > 0)
eecd1362
LP
1108 continue;
1109
84286536 1110 if (m->action_what != 0 && !m->action_job) {
eecd1362
LP
1111 usec_t x, y;
1112
1113 x = now(CLOCK_MONOTONIC);
314b4b0a 1114 y = m->action_timestamp + m->inhibit_delay_max;
eecd1362 1115
cc377381 1116 us = x >= y ? 0 : y - x;
eecd1362
LP
1117 }
1118
cc377381
LP
1119 r = sd_event_run(m->event, us);
1120 if (r < 0)
1121 return r;
20263082 1122 }
20263082
LP
1123}
1124
193197e8 1125static int manager_parse_config_file(Manager *m) {
193197e8
LP
1126 assert(m);
1127
e8461023
JT
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);
193197e8
LP
1133}
1134
20263082
LP
1135int main(int argc, char *argv[]) {
1136 Manager *m = NULL;
5eda94dd 1137 int r;
20263082
LP
1138
1139 log_set_target(LOG_TARGET_AUTO);
3eff4208 1140 log_set_facility(LOG_AUTH);
20263082
LP
1141 log_parse_environment();
1142 log_open();
1143
4c12626c
LP
1144 umask(0022);
1145
20263082
LP
1146 if (argc != 1) {
1147 log_error("This program takes no arguments.");
1148 r = -EINVAL;
1149 goto finish;
1150 }
1151
bb27ff66
LP
1152 /* Always create the directories people can create inotify
1153 * watches in. Note that some applications might check for the
ab06eef8 1154 * existence of /run/systemd/seats/ to determine whether
bb27ff66
LP
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
20263082
LP
1161 m = manager_new();
1162 if (!m) {
0d0f0c50 1163 r = log_oom();
20263082
LP
1164 goto finish;
1165 }
1166
193197e8
LP
1167 manager_parse_config_file(m);
1168
20263082
LP
1169 r = manager_startup(m);
1170 if (r < 0) {
da927ba9 1171 log_error_errno(r, "Failed to fully start up daemon: %m");
20263082
LP
1172 goto finish;
1173 }
1174
de0671ee 1175 log_debug("systemd-logind running as pid "PID_FMT, getpid());
e6960940
LP
1176
1177 sd_notify(false,
1178 "READY=1\n"
1179 "STATUS=Processing requests...");
1180
20263082
LP
1181 r = manager_run(m);
1182
de0671ee 1183 log_debug("systemd-logind stopped as pid "PID_FMT, getpid());
e6960940 1184
20263082 1185finish:
e6960940 1186 sd_notify(false,
af4ec430 1187 "STOPPING=1\n"
e6960940
LP
1188 "STATUS=Shutting down...");
1189
20263082
LP
1190 if (m)
1191 manager_free(m);
1192
1193 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1194}