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