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