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