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