]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind.c
socket: introduce SELinuxContextFromNet option
[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
293 log_error("Failed to open /run/systemd/seats: %m");
294 return -errno;
295 }
296
9444b1f2 297 FOREACH_DIRENT(de, d, return -errno) {
20263082
LP
298 Seat *s;
299 int k;
300
301 if (!dirent_is_file(de))
302 continue;
303
304 s = hashmap_get(m->seats, de->d_name);
305 if (!s) {
306 unlinkat(dirfd(d), de->d_name, 0);
307 continue;
308 }
309
310 k = seat_load(s);
311 if (k < 0)
312 r = k;
313 }
314
14c3baca
LP
315 return r;
316}
20263082 317
14c3baca 318static int manager_enumerate_linger_users(Manager *m) {
9444b1f2 319 _cleanup_closedir_ DIR *d = NULL;
14c3baca
LP
320 struct dirent *de;
321 int r = 0;
322
9444b1f2
LP
323 assert(m);
324
14c3baca
LP
325 d = opendir("/var/lib/systemd/linger");
326 if (!d) {
327 if (errno == ENOENT)
328 return 0;
329
330 log_error("Failed to open /var/lib/systemd/linger/: %m");
331 return -errno;
332 }
333
9444b1f2 334 FOREACH_DIRENT(de, d, return -errno) {
14c3baca
LP
335 int k;
336
337 if (!dirent_is_file(de))
20263082
LP
338 continue;
339
14c3baca
LP
340 k = manager_add_user_by_name(m, de->d_name, NULL);
341 if (k < 0) {
342 log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
343 r = k;
20263082
LP
344 }
345 }
346
20263082
LP
347 return r;
348}
349
9588bc32 350static int manager_enumerate_users(Manager *m) {
9444b1f2 351 _cleanup_closedir_ DIR *d = NULL;
20263082 352 struct dirent *de;
14c3baca 353 int r, k;
20263082
LP
354
355 assert(m);
356
9444b1f2 357 /* Add lingering users */
b3629c7d 358 r = manager_enumerate_linger_users(m);
14c3baca 359
9444b1f2 360 /* Read in user data stored on disk */
20263082
LP
361 d = opendir("/run/systemd/users");
362 if (!d) {
363 if (errno == ENOENT)
364 return 0;
365
366 log_error("Failed to open /run/systemd/users: %m");
367 return -errno;
368 }
369
9444b1f2 370 FOREACH_DIRENT(de, d, return -errno) {
20263082 371 User *u;
20263082
LP
372
373 if (!dirent_is_file(de))
374 continue;
375
9444b1f2 376 k = manager_add_user_by_name(m, de->d_name, &u);
20263082 377 if (k < 0) {
9444b1f2 378 log_error("Failed to add user by file name %s: %s", de->d_name, strerror(-k));
20263082 379
9444b1f2 380 r = k;
20263082
LP
381 continue;
382 }
383
9444b1f2
LP
384 user_add_to_gc_queue(u);
385
20263082
LP
386 k = user_load(u);
387 if (k < 0)
388 r = k;
389 }
390
20263082
LP
391 return r;
392}
393
9588bc32 394static int manager_enumerate_sessions(Manager *m) {
9444b1f2
LP
395 _cleanup_closedir_ DIR *d = NULL;
396 struct dirent *de;
20263082
LP
397 int r = 0;
398
9444b1f2
LP
399 assert(m);
400
401 /* Read in session data stored on disk */
402 d = opendir("/run/systemd/sessions");
403 if (!d) {
404 if (errno == ENOENT)
405 return 0;
406
407 log_error("Failed to open /run/systemd/sessions: %m");
408 return -errno;
409 }
410
411 FOREACH_DIRENT(de, d, return -errno) {
412 struct Session *s;
20263082
LP
413 int k;
414
9444b1f2 415 if (!dirent_is_file(de))
14c3baca
LP
416 continue;
417
4b549144
ZJS
418 if (!session_id_valid(de->d_name)) {
419 log_warning("Invalid session file name '%s', ignoring.", de->d_name);
420 r = -EINVAL;
421 continue;
422 }
423
9444b1f2 424 k = manager_add_session(m, de->d_name, &s);
20263082 425 if (k < 0) {
9444b1f2 426 log_error("Failed to add session by file name %s: %s", de->d_name, strerror(-k));
20263082 427
20263082
LP
428 r = k;
429 continue;
430 }
431
9444b1f2 432 session_add_to_gc_queue(s);
20263082 433
9444b1f2 434 k = session_load(s);
20263082
LP
435 if (k < 0)
436 r = k;
437 }
438
439 return r;
440}
441
9588bc32 442static int manager_enumerate_inhibitors(Manager *m) {
9444b1f2 443 _cleanup_closedir_ DIR *d = NULL;
20263082
LP
444 struct dirent *de;
445 int r = 0;
446
447 assert(m);
448
9444b1f2 449 d = opendir("/run/systemd/inhibit");
20263082
LP
450 if (!d) {
451 if (errno == ENOENT)
452 return 0;
453
9444b1f2 454 log_error("Failed to open /run/systemd/inhibit: %m");
20263082
LP
455 return -errno;
456 }
457
9444b1f2 458 FOREACH_DIRENT(de, d, return -errno) {
20263082 459 int k;
9444b1f2 460 Inhibitor *i;
20263082
LP
461
462 if (!dirent_is_file(de))
463 continue;
464
9444b1f2
LP
465 k = manager_add_inhibitor(m, de->d_name, &i);
466 if (k < 0) {
467 log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
468 r = k;
20263082
LP
469 continue;
470 }
471
9444b1f2 472 k = inhibitor_load(i);
20263082
LP
473 if (k < 0)
474 r = k;
475 }
476
20263082
LP
477 return r;
478}
479
cc377381 480static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
7b77ed8c 481 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
cc377381 482 Manager *m = userdata;
20263082
LP
483
484 assert(m);
485
30ed21ce 486 d = udev_monitor_receive_device(m->udev_seat_monitor);
20263082
LP
487 if (!d)
488 return -ENOMEM;
489
7b77ed8c
LP
490 manager_process_seat_device(m, d);
491 return 0;
30ed21ce
LP
492}
493
cc377381 494static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
7b77ed8c 495 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
cc377381 496 Manager *m = userdata;
718d006a
DH
497
498 assert(m);
499
500 d = udev_monitor_receive_device(m->udev_device_monitor);
501 if (!d)
502 return -ENOMEM;
503
7b77ed8c
LP
504 manager_process_seat_device(m, d);
505 return 0;
718d006a
DH
506}
507
cc377381 508static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
7b77ed8c 509 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
cc377381 510 Manager *m = userdata;
30ed21ce
LP
511 const char *name;
512
513 assert(m);
514
515 d = udev_monitor_receive_device(m->udev_vcsa_monitor);
516 if (!d)
517 return -ENOMEM;
518
519 name = udev_device_get_sysname(d);
520
521 /* Whenever a VCSA device is removed try to reallocate our
522 * VTs, to make sure our auto VTs never go away. */
523
524 if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
7b77ed8c 525 seat_preallocate_vts(m->seat0);
30ed21ce 526
7b77ed8c 527 return 0;
20263082
LP
528}
529
cc377381 530static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
7b77ed8c 531 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
cc377381 532 Manager *m = userdata;
069cfc85
LP
533
534 assert(m);
535
536 d = udev_monitor_receive_device(m->udev_button_monitor);
537 if (!d)
538 return -ENOMEM;
539
7b77ed8c
LP
540 manager_process_button_device(m, d);
541 return 0;
069cfc85
LP
542}
543
cc377381
LP
544static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
545 Manager *m = userdata;
546
20263082 547 assert(m);
92432fcc 548 assert(m->seat0);
cc377381 549 assert(m->console_active_fd == fd);
20263082 550
92432fcc 551 seat_read_active_vt(m->seat0);
20263082
LP
552 return 0;
553}
554
98a77df5
LP
555static int manager_reserve_vt(Manager *m) {
556 _cleanup_free_ char *p = NULL;
557
558 assert(m);
559
560 if (m->reserve_vt <= 0)
561 return 0;
562
563 if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
564 return log_oom();
565
566 m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
567 if (m->reserve_vt_fd < 0) {
d4d882e5
LP
568
569 /* Don't complain on VT-less systems */
570 if (errno != ENOENT)
571 log_warning("Failed to pin reserved VT: %m");
98a77df5
LP
572 return -errno;
573 }
574
575 return 0;
576}
577
cc377381
LP
578static int manager_connect_bus(Manager *m) {
579 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
580 int r;
31b79c2b 581
cc377381
LP
582 assert(m);
583 assert(!m->bus);
31b79c2b 584
76b54375 585 r = sd_bus_default_system(&m->bus);
cc377381
LP
586 if (r < 0) {
587 log_error("Failed to connect to system bus: %s", strerror(-r));
588 return r;
f8e2fb7b 589 }
31b79c2b 590
19befb2d 591 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
cc377381
LP
592 if (r < 0) {
593 log_error("Failed to add manager object vtable: %s", strerror(-r));
594 return r;
f8e2fb7b
LP
595 }
596
19befb2d 597 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
cc377381
LP
598 if (r < 0) {
599 log_error("Failed to add seat object vtable: %s", strerror(-r));
600 return r;
069cfc85
LP
601 }
602
19befb2d 603 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
cc377381
LP
604 if (r < 0) {
605 log_error("Failed to add seat enumerator: %s", strerror(-r));
606 return r;
607 }
20263082 608
19befb2d 609 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
cc377381
LP
610 if (r < 0) {
611 log_error("Failed to add session object vtable: %s", strerror(-r));
612 return r;
613 }
20263082 614
19befb2d 615 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
cc377381
LP
616 if (r < 0) {
617 log_error("Failed to add session enumerator: %s", strerror(-r));
618 return r;
619 }
20263082 620
19befb2d 621 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
cc377381
LP
622 if (r < 0) {
623 log_error("Failed to add user object vtable: %s", strerror(-r));
624 return r;
20263082
LP
625 }
626
19befb2d 627 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
cc377381
LP
628 if (r < 0) {
629 log_error("Failed to add user enumerator: %s", strerror(-r));
630 return r;
20263082
LP
631 }
632
cc377381 633 r = sd_bus_add_match(m->bus,
19befb2d 634 NULL,
cc377381
LP
635 "type='signal',"
636 "sender='org.freedesktop.DBus',"
637 "interface='org.freedesktop.DBus',"
638 "member='NameOwnerChanged',"
639 "path='/org/freedesktop/DBus'",
640 match_name_owner_changed, m);
641 if (r < 0) {
642 log_error("Failed to add match for NameOwnerChanged: %s", strerror(-r));
643 return r;
e8b212fe
DH
644 }
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.systemd1.Manager',"
651 "member='JobRemoved',"
652 "path='/org/freedesktop/systemd1'",
653 match_job_removed, m);
654 if (r < 0) {
655 log_error("Failed to add match for JobRemoved: %s", strerror(-r));
656 return r;
943aca8e
LP
657 }
658
cc377381 659 r = sd_bus_add_match(m->bus,
19befb2d 660 NULL,
cc377381
LP
661 "type='signal',"
662 "sender='org.freedesktop.systemd1',"
663 "interface='org.freedesktop.systemd1.Manager',"
664 "member='UnitRemoved',"
665 "path='/org/freedesktop/systemd1'",
666 match_unit_removed, m);
667 if (r < 0) {
668 log_error("Failed to add match for UnitRemoved: %s", strerror(-r));
669 return r;
fb6becb4
LP
670 }
671
cc377381 672 r = sd_bus_add_match(m->bus,
19befb2d 673 NULL,
cc377381
LP
674 "type='signal',"
675 "sender='org.freedesktop.systemd1',"
676 "interface='org.freedesktop.DBus.Properties',"
677 "member='PropertiesChanged'",
678 match_properties_changed, m);
679 if (r < 0) {
680 log_error("Failed to add match for PropertiesChanged: %s", strerror(-r));
681 return r;
fb6becb4
LP
682 }
683
cc377381 684 r = sd_bus_add_match(m->bus,
19befb2d 685 NULL,
cc377381
LP
686 "type='signal',"
687 "sender='org.freedesktop.systemd1',"
688 "interface='org.freedesktop.systemd1.Manager',"
689 "member='Reloading',"
690 "path='/org/freedesktop/systemd1'",
691 match_reloading, m);
692 if (r < 0) {
693 log_error("Failed to add match for Reloading: %s", strerror(-r));
694 return r;
6797c324
LP
695 }
696
cc377381 697 r = sd_bus_call_method(
fb6becb4
LP
698 m->bus,
699 "org.freedesktop.systemd1",
700 "/org/freedesktop/systemd1",
701 "org.freedesktop.systemd1.Manager",
702 "Subscribe",
fb6becb4 703 &error,
cc377381 704 NULL, NULL);
fb6becb4 705 if (r < 0) {
cc377381
LP
706 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
707 return r;
20263082
LP
708 }
709
5bb658a1 710 r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
cc377381
LP
711 if (r < 0) {
712 log_error("Failed to register name: %s", strerror(-r));
713 return r;
bafd4449
LP
714 }
715
cc377381
LP
716 r = sd_bus_attach_event(m->bus, m->event, 0);
717 if (r < 0) {
718 log_error("Failed to attach bus to event loop: %s", strerror(-r));
719 return r;
20263082
LP
720 }
721
20263082 722 return 0;
20263082
LP
723}
724
92683ad2
DH
725static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
726 Manager *m = data;
727 Session *active, *iter;
728
729 /*
730 * We got a VT-switch signal and we have to acknowledge it immediately.
731 * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
732 * old user-space might run multiple sessions on a single VT, *sigh*.
733 * Therefore, we have to iterate all sessions and find one with a vtfd
734 * on the requested VT.
735 * As only VTs with active controllers have VT_PROCESS set, our current
736 * notion of the active VT might be wrong (for instance if the switch
737 * happens while we setup VT_PROCESS). Therefore, read the current VT
738 * first and then use s->active->vtnr as reference. Note that this is
739 * not racy, as no further VT-switch can happen as long as we're in
740 * synchronous VT_PROCESS mode.
741 */
742
743 assert(m->seat0);
744 seat_read_active_vt(m->seat0);
745
746 active = m->seat0->active;
747 if (!active || active->vtnr < 1) {
748 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
749 return 0;
750 }
751
752 if (active->vtfd >= 0) {
753 ioctl(active->vtfd, VT_RELDISP, 1);
754 } else {
755 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
756 if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
757 ioctl(iter->vtfd, VT_RELDISP, 1);
758 break;
759 }
760 }
761 }
762
763 return 0;
764}
765
20263082 766static int manager_connect_console(Manager *m) {
cc377381 767 int r;
20263082
LP
768
769 assert(m);
770 assert(m->console_active_fd < 0);
771
74afee9c
LP
772 /* On certain architectures (S390 and Xen, and containers),
773 /dev/tty0 does not exist, so don't fail if we can't open
774 it. */
cc377381 775 if (access("/dev/tty0", F_OK) < 0)
74afee9c 776 return 0;
74afee9c 777
20263082
LP
778 m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
779 if (m->console_active_fd < 0) {
cdc564d2
MS
780
781 /* On some systems the device node /dev/tty0 may exist
782 * even though /sys/class/tty/tty0 does not. */
783 if (errno == ENOENT)
784 return 0;
785
20263082
LP
786 log_error("Failed to open /sys/class/tty/tty0/active: %m");
787 return -errno;
788 }
789
151b9b96 790 r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
cc377381
LP
791 if (r < 0) {
792 log_error("Failed to watch foreground console");
793 return r;
794 }
20263082 795
92683ad2
DH
796 /*
797 * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
798 * as VT-acquire signal. We ignore any acquire-events (yes, we still
799 * have to provide a valid signal-number for it!) and acknowledge all
800 * release events immediately.
801 */
802
803 if (SIGRTMIN + 1 > SIGRTMAX) {
804 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
805 return -EINVAL;
806 }
807
808 r = ignore_signals(SIGRTMIN + 1, -1);
809 if (r < 0) {
810 log_error("Cannot ignore SIGRTMIN + 1: %s", strerror(-r));
811 return r;
812 }
813
814 r = sigprocmask_many(SIG_BLOCK, SIGRTMIN, -1);
815 if (r < 0) {
816 log_error("Cannot block SIGRTMIN: %s", strerror(-r));
817 return r;
818 }
819
820 r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
821 if (r < 0)
822 return r;
823
20263082
LP
824 return 0;
825}
826
827static int manager_connect_udev(Manager *m) {
14c3baca 828 int r;
20263082
LP
829
830 assert(m);
30ed21ce 831 assert(!m->udev_seat_monitor);
718d006a 832 assert(!m->udev_device_monitor);
30ed21ce 833 assert(!m->udev_vcsa_monitor);
069cfc85 834 assert(!m->udev_button_monitor);
20263082 835
30ed21ce
LP
836 m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
837 if (!m->udev_seat_monitor)
20263082
LP
838 return -ENOMEM;
839
2d96536d 840 r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
14c3baca
LP
841 if (r < 0)
842 return r;
20263082 843
30ed21ce 844 r = udev_monitor_enable_receiving(m->udev_seat_monitor);
14c3baca
LP
845 if (r < 0)
846 return r;
20263082 847
151b9b96 848 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
849 if (r < 0)
850 return r;
069cfc85 851
718d006a
DH
852 m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
853 if (!m->udev_device_monitor)
854 return -ENOMEM;
855
856 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
857 if (r < 0)
858 return r;
859
860 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
861 if (r < 0)
862 return r;
863
864 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
865 if (r < 0)
866 return r;
867
868 r = udev_monitor_enable_receiving(m->udev_device_monitor);
869 if (r < 0)
870 return r;
871
151b9b96 872 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
873 if (r < 0)
874 return r;
718d006a 875
6de0e0e5 876 /* Don't watch keys if nobody cares */
beaafb2e 877 if (m->handle_power_key != HANDLE_IGNORE ||
8e7fd6ad
LP
878 m->handle_suspend_key != HANDLE_IGNORE ||
879 m->handle_hibernate_key != HANDLE_IGNORE ||
3c56cab4
BW
880 m->handle_lid_switch != HANDLE_IGNORE ||
881 m->handle_lid_switch_docked != HANDLE_IGNORE) {
069cfc85 882
6de0e0e5
LP
883 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
884 if (!m->udev_button_monitor)
885 return -ENOMEM;
069cfc85 886
6de0e0e5
LP
887 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
888 if (r < 0)
889 return r;
069cfc85 890
6de0e0e5
LP
891 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
892 if (r < 0)
893 return r;
069cfc85 894
6de0e0e5
LP
895 r = udev_monitor_enable_receiving(m->udev_button_monitor);
896 if (r < 0)
897 return r;
069cfc85 898
151b9b96 899 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
900 if (r < 0)
901 return r;
6de0e0e5 902 }
069cfc85 903
976c088a 904 /* Don't bother watching VCSA devices, if nobody cares */
6de0e0e5 905 if (m->n_autovts > 0 && m->console_active_fd >= 0) {
30ed21ce 906
6de0e0e5
LP
907 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
908 if (!m->udev_vcsa_monitor)
909 return -ENOMEM;
30ed21ce 910
6de0e0e5
LP
911 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
912 if (r < 0)
913 return r;
30ed21ce 914
6de0e0e5
LP
915 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
916 if (r < 0)
917 return r;
30ed21ce 918
151b9b96 919 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
920 if (r < 0)
921 return r;
6de0e0e5 922 }
20263082
LP
923
924 return 0;
925}
926
4a4b033f 927void manager_gc(Manager *m, bool drop_not_started) {
14c3baca
LP
928 Seat *seat;
929 Session *session;
930 User *user;
931
932 assert(m);
933
934 while ((seat = m->seat_gc_queue)) {
71fda00f 935 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
14c3baca
LP
936 seat->in_gc_queue = false;
937
cc377381 938 if (!seat_check_gc(seat, drop_not_started)) {
9bb69af4 939 seat_stop(seat, false);
14c3baca
LP
940 seat_free(seat);
941 }
942 }
943
944 while ((session = m->session_gc_queue)) {
71fda00f 945 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
14c3baca
LP
946 session->in_gc_queue = false;
947
5f41d1f1
LP
948 /* First, if we are not closing yet, initiate stopping */
949 if (!session_check_gc(session, drop_not_started) &&
950 session_get_state(session) != SESSION_CLOSING)
9bb69af4 951 session_stop(session, false);
5f41d1f1
LP
952
953 /* Normally, this should make the session busy again,
954 * if it doesn't then let's get rid of it
955 * immediately */
956 if (!session_check_gc(session, drop_not_started)) {
405e0255 957 session_finalize(session);
14c3baca
LP
958 session_free(session);
959 }
960 }
961
962 while ((user = m->user_gc_queue)) {
71fda00f 963 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
14c3baca
LP
964 user->in_gc_queue = false;
965
b58b227a
DH
966 /* First step: queue stop jobs */
967 if (!user_check_gc(user, drop_not_started))
9bb69af4 968 user_stop(user, false);
5f41d1f1 969
b58b227a 970 /* Second step: finalize user */
5f41d1f1 971 if (!user_check_gc(user, drop_not_started)) {
405e0255 972 user_finalize(user);
14c3baca
LP
973 user_free(user);
974 }
975 }
976}
977
cc377381
LP
978static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
979 Manager *m = userdata;
23406ce5 980 struct dual_timestamp since;
cc377381 981 usec_t n, elapse;
23406ce5 982 int r;
23406ce5
LP
983
984 assert(m);
985
986 if (m->idle_action == HANDLE_IGNORE ||
cc377381
LP
987 m->idle_action_usec <= 0)
988 return 0;
23406ce5 989
23406ce5
LP
990 n = now(CLOCK_MONOTONIC);
991
992 r = manager_get_idle_hint(m, &since);
993 if (r <= 0)
39ccc87c 994 /* Not idle. Let's check if after a timeout it might be idle then. */
cc377381 995 elapse = n + m->idle_action_usec;
23406ce5
LP
996 else {
997 /* Idle! Let's see if it's time to do something, or if
998 * we shall sleep for longer. */
999
1000 if (n >= since.monotonic + m->idle_action_usec &&
1001 (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1002 log_info("System idle. Taking action.");
1003
1004 manager_handle_action(m, 0, m->idle_action, false, false);
1005 m->idle_action_not_before_usec = n;
1006 }
1007
cc377381 1008 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
23406ce5
LP
1009 }
1010
cc377381 1011 if (!m->idle_action_event_source) {
23406ce5 1012
6a0f1f6d
LP
1013 r = sd_event_add_time(
1014 m->event,
1015 &m->idle_action_event_source,
1016 CLOCK_MONOTONIC,
1017 elapse, USEC_PER_SEC*30,
1018 manager_dispatch_idle_action, m);
cc377381
LP
1019 if (r < 0) {
1020 log_error("Failed to add idle event source: %s", strerror(-r));
1021 return r;
23406ce5
LP
1022 }
1023
718db961 1024 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
cc377381
LP
1025 if (r < 0) {
1026 log_error("Failed to set idle event source priority: %s", strerror(-r));
1027 return r;
1028 }
1029 } else {
1030 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1031 if (r < 0) {
1032 log_error("Failed to set idle event timer: %s", strerror(-r));
1033 return r;
23406ce5 1034 }
23406ce5 1035
cc377381
LP
1036 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1037 if (r < 0) {
1038 log_error("Failed to enable idle event timer: %s", strerror(-r));
1039 return r;
1040 }
23406ce5
LP
1041 }
1042
1043 return 0;
23406ce5 1044}
cc377381 1045
20263082
LP
1046int manager_startup(Manager *m) {
1047 int r;
14c3baca
LP
1048 Seat *seat;
1049 Session *session;
1050 User *user;
ed4ba7e4 1051 Button *button;
f8e2fb7b 1052 Inhibitor *inhibitor;
14c3baca 1053 Iterator i;
20263082
LP
1054
1055 assert(m);
20263082 1056
976c088a
LP
1057 /* Connect to console */
1058 r = manager_connect_console(m);
20263082
LP
1059 if (r < 0)
1060 return r;
1061
976c088a
LP
1062 /* Connect to udev */
1063 r = manager_connect_udev(m);
cc377381
LP
1064 if (r < 0) {
1065 log_error("Failed to create udev watchers: %s", strerror(-r));
20263082 1066 return r;
cc377381 1067 }
20263082
LP
1068
1069 /* Connect to the bus */
1070 r = manager_connect_bus(m);
1071 if (r < 0)
1072 return r;
1073
14c3baca 1074 /* Instantiate magic seat 0 */
92432fcc 1075 r = manager_add_seat(m, "seat0", &m->seat0);
cc377381
LP
1076 if (r < 0) {
1077 log_error("Failed to add seat0: %s", strerror(-r));
14c3baca 1078 return r;
cc377381 1079 }
14c3baca 1080
f9cd6be1
LP
1081 r = manager_set_lid_switch_ignore(m, 0 + IGNORE_LID_SWITCH_STARTUP_USEC);
1082 if (r < 0)
1083 log_warning("Failed to set up lid switch ignore event source: %s", strerror(-r));
1084
20263082 1085 /* Deserialize state */
042f5988
ZJS
1086 r = manager_enumerate_devices(m);
1087 if (r < 0)
1088 log_warning("Device enumeration failed: %s", strerror(-r));
1089
1090 r = manager_enumerate_seats(m);
1091 if (r < 0)
1092 log_warning("Seat enumeration failed: %s", strerror(-r));
1093
1094 r = manager_enumerate_users(m);
1095 if (r < 0)
1096 log_warning("User enumeration failed: %s", strerror(-r));
1097
1098 r = manager_enumerate_sessions(m);
1099 if (r < 0)
1100 log_warning("Session enumeration failed: %s", strerror(-r));
1101
1102 r = manager_enumerate_inhibitors(m);
1103 if (r < 0)
1104 log_warning("Inhibitor enumeration failed: %s", strerror(-r));
1105
1106 r = manager_enumerate_buttons(m);
1107 if (r < 0)
1108 log_warning("Button enumeration failed: %s", strerror(-r));
20263082 1109
4a4b033f
LP
1110 /* Remove stale objects before we start them */
1111 manager_gc(m, false);
1112
98a77df5
LP
1113 /* Reserve the special reserved VT */
1114 manager_reserve_vt(m);
1115
14c3baca
LP
1116 /* And start everything */
1117 HASHMAP_FOREACH(seat, m->seats, i)
1118 seat_start(seat);
1119
1120 HASHMAP_FOREACH(user, m->users, i)
1121 user_start(user);
1122
1123 HASHMAP_FOREACH(session, m->sessions, i)
1124 session_start(session);
20263082 1125
f8e2fb7b
LP
1126 HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1127 inhibitor_start(inhibitor);
1128
ed4ba7e4 1129 HASHMAP_FOREACH(button, m->buttons, i)
2d62c530 1130 button_check_switches(button);
ed4ba7e4 1131
cc377381 1132 manager_dispatch_idle_action(NULL, 0, m);
23406ce5 1133
20263082
LP
1134 return 0;
1135}
1136
1137int manager_run(Manager *m) {
cc377381
LP
1138 int r;
1139
20263082
LP
1140 assert(m);
1141
1142 for (;;) {
cc377381
LP
1143 usec_t us = (uint64_t) -1;
1144
1145 r = sd_event_get_state(m->event);
1146 if (r < 0)
1147 return r;
1148 if (r == SD_EVENT_FINISHED)
1149 return 0;
20263082 1150
4a4b033f 1151 manager_gc(m, true);
14c3baca 1152
d889a206 1153 if (manager_dispatch_delayed(m) > 0)
eecd1362
LP
1154 continue;
1155
84286536 1156 if (m->action_what != 0 && !m->action_job) {
eecd1362
LP
1157 usec_t x, y;
1158
1159 x = now(CLOCK_MONOTONIC);
314b4b0a 1160 y = m->action_timestamp + m->inhibit_delay_max;
eecd1362 1161
cc377381 1162 us = x >= y ? 0 : y - x;
eecd1362
LP
1163 }
1164
cc377381
LP
1165 r = sd_event_run(m->event, us);
1166 if (r < 0)
1167 return r;
20263082 1168 }
20263082
LP
1169}
1170
193197e8 1171static int manager_parse_config_file(Manager *m) {
193197e8
LP
1172 assert(m);
1173
36f822c4
ZJS
1174 return config_parse(NULL, "/etc/systemd/logind.conf", NULL,
1175 "Login\0",
1176 config_item_perf_lookup, logind_gperf_lookup,
1177 false, false, true, m);
193197e8
LP
1178}
1179
20263082
LP
1180int main(int argc, char *argv[]) {
1181 Manager *m = NULL;
5eda94dd 1182 int r;
20263082
LP
1183
1184 log_set_target(LOG_TARGET_AUTO);
3eff4208 1185 log_set_facility(LOG_AUTH);
20263082
LP
1186 log_parse_environment();
1187 log_open();
1188
4c12626c
LP
1189 umask(0022);
1190
20263082
LP
1191 if (argc != 1) {
1192 log_error("This program takes no arguments.");
1193 r = -EINVAL;
1194 goto finish;
1195 }
1196
bb27ff66
LP
1197 /* Always create the directories people can create inotify
1198 * watches in. Note that some applications might check for the
ab06eef8 1199 * existence of /run/systemd/seats/ to determine whether
bb27ff66
LP
1200 * logind is available, so please always make sure this check
1201 * stays in. */
1202 mkdir_label("/run/systemd/seats", 0755);
1203 mkdir_label("/run/systemd/users", 0755);
1204 mkdir_label("/run/systemd/sessions", 0755);
1205
20263082
LP
1206 m = manager_new();
1207 if (!m) {
0d0f0c50 1208 r = log_oom();
20263082
LP
1209 goto finish;
1210 }
1211
193197e8
LP
1212 manager_parse_config_file(m);
1213
20263082
LP
1214 r = manager_startup(m);
1215 if (r < 0) {
1216 log_error("Failed to fully start up daemon: %s", strerror(-r));
1217 goto finish;
1218 }
1219
de0671ee 1220 log_debug("systemd-logind running as pid "PID_FMT, getpid());
e6960940
LP
1221
1222 sd_notify(false,
1223 "READY=1\n"
1224 "STATUS=Processing requests...");
1225
20263082
LP
1226 r = manager_run(m);
1227
de0671ee 1228 log_debug("systemd-logind stopped as pid "PID_FMT, getpid());
e6960940 1229
20263082 1230finish:
e6960940 1231 sd_notify(false,
af4ec430 1232 "STOPPING=1\n"
e6960940
LP
1233 "STATUS=Shutting down...");
1234
20263082
LP
1235 if (m)
1236 manager_free(m);
1237
1238 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1239}