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