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