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