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