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