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