chiark / gitweb /
unit: add ConditionACPower=
[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 <pwd.h>
24 #include <libudev.h>
25 #include <fcntl.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/epoll.h>
29 #include <sys/ioctl.h>
30 #include <linux/vt.h>
31 #include <sys/timerfd.h>
32
33 #include <systemd/sd-daemon.h>
34
35 #include "logind.h"
36 #include "dbus-common.h"
37 #include "dbus-loop.h"
38 #include "strv.h"
39 #include "conf-parser.h"
40
41 Manager *manager_new(void) {
42         Manager *m;
43
44         m = new0(Manager, 1);
45         if (!m)
46                 return NULL;
47
48         m->console_active_fd = -1;
49         m->bus_fd = -1;
50         m->udev_seat_fd = -1;
51         m->udev_vcsa_fd = -1;
52         m->udev_button_fd = -1;
53         m->epoll_fd = -1;
54         m->reserve_vt_fd = -1;
55
56         m->n_autovts = 6;
57         m->reserve_vt = 6;
58         m->inhibit_delay_max = 5 * USEC_PER_SEC;
59         m->handle_power_key = HANDLE_POWEROFF;
60         m->handle_suspend_key = HANDLE_SUSPEND;
61         m->handle_hibernate_key = HANDLE_HIBERNATE;
62         m->handle_lid_switch = HANDLE_SUSPEND;
63         m->lid_switch_ignore_inhibited = true;
64
65         m->idle_action_fd = -1;
66         m->idle_action_usec = 30 * USEC_PER_MINUTE;
67         m->idle_action = HANDLE_IGNORE;
68         m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
69
70         m->devices = hashmap_new(string_hash_func, string_compare_func);
71         m->seats = hashmap_new(string_hash_func, string_compare_func);
72         m->sessions = hashmap_new(string_hash_func, string_compare_func);
73         m->users = hashmap_new(trivial_hash_func, trivial_compare_func);
74         m->inhibitors = hashmap_new(string_hash_func, string_compare_func);
75         m->buttons = hashmap_new(string_hash_func, string_compare_func);
76
77         m->user_cgroups = hashmap_new(string_hash_func, string_compare_func);
78         m->session_cgroups = hashmap_new(string_hash_func, string_compare_func);
79
80         m->session_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
81         m->inhibitor_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
82         m->button_fds = hashmap_new(trivial_hash_func, trivial_compare_func);
83
84         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons ||
85             !m->user_cgroups || !m->session_cgroups ||
86             !m->session_fds || !m->inhibitor_fds || !m->button_fds) {
87                 manager_free(m);
88                 return NULL;
89         }
90
91         m->reset_controllers = strv_new("cpu", NULL);
92         m->kill_exclude_users = strv_new("root", NULL);
93         if (!m->reset_controllers || !m->kill_exclude_users) {
94                 manager_free(m);
95                 return NULL;
96         }
97
98         m->udev = udev_new();
99         if (!m->udev) {
100                 manager_free(m);
101                 return NULL;
102         }
103
104         if (cg_get_user_path(&m->cgroup_path) < 0) {
105                 manager_free(m);
106                 return NULL;
107         }
108
109         return m;
110 }
111
112 void manager_free(Manager *m) {
113         Session *session;
114         User *u;
115         Device *d;
116         Seat *s;
117         Inhibitor *i;
118         Button *b;
119
120         assert(m);
121
122         while ((session = hashmap_first(m->sessions)))
123                 session_free(session);
124
125         while ((u = hashmap_first(m->users)))
126                 user_free(u);
127
128         while ((d = hashmap_first(m->devices)))
129                 device_free(d);
130
131         while ((s = hashmap_first(m->seats)))
132                 seat_free(s);
133
134         while ((i = hashmap_first(m->inhibitors)))
135                 inhibitor_free(i);
136
137         while ((b = hashmap_first(m->buttons)))
138                 button_free(b);
139
140         hashmap_free(m->devices);
141         hashmap_free(m->seats);
142         hashmap_free(m->sessions);
143         hashmap_free(m->users);
144         hashmap_free(m->inhibitors);
145         hashmap_free(m->buttons);
146
147         hashmap_free(m->user_cgroups);
148         hashmap_free(m->session_cgroups);
149
150         hashmap_free(m->session_fds);
151         hashmap_free(m->inhibitor_fds);
152         hashmap_free(m->button_fds);
153
154         if (m->console_active_fd >= 0)
155                 close_nointr_nofail(m->console_active_fd);
156
157         if (m->udev_seat_monitor)
158                 udev_monitor_unref(m->udev_seat_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         if (m->bus) {
168                 dbus_connection_flush(m->bus);
169                 dbus_connection_close(m->bus);
170                 dbus_connection_unref(m->bus);
171         }
172
173         if (m->bus_fd >= 0)
174                 close_nointr_nofail(m->bus_fd);
175
176         if (m->epoll_fd >= 0)
177                 close_nointr_nofail(m->epoll_fd);
178
179         if (m->reserve_vt_fd >= 0)
180                 close_nointr_nofail(m->reserve_vt_fd);
181
182         if (m->idle_action_fd >= 0)
183                 close_nointr_nofail(m->idle_action_fd);
184
185         strv_free(m->controllers);
186         strv_free(m->reset_controllers);
187         strv_free(m->kill_only_users);
188         strv_free(m->kill_exclude_users);
189
190         free(m->cgroup_path);
191         free(m);
192 }
193
194 int manager_add_device(Manager *m, const char *sysfs, Device **_device) {
195         Device *d;
196
197         assert(m);
198         assert(sysfs);
199
200         d = hashmap_get(m->devices, sysfs);
201         if (d) {
202                 if (_device)
203                         *_device = d;
204
205                 return 0;
206         }
207
208         d = device_new(m, sysfs);
209         if (!d)
210                 return -ENOMEM;
211
212         if (_device)
213                 *_device = d;
214
215         return 0;
216 }
217
218 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
219         Seat *s;
220
221         assert(m);
222         assert(id);
223
224         s = hashmap_get(m->seats, id);
225         if (s) {
226                 if (_seat)
227                         *_seat = s;
228
229                 return 0;
230         }
231
232         s = seat_new(m, id);
233         if (!s)
234                 return -ENOMEM;
235
236         if (_seat)
237                 *_seat = s;
238
239         return 0;
240 }
241
242 int manager_add_session(Manager *m, User *u, const char *id, Session **_session) {
243         Session *s;
244
245         assert(m);
246         assert(id);
247
248         s = hashmap_get(m->sessions, id);
249         if (s) {
250                 if (_session)
251                         *_session = s;
252
253                 return 0;
254         }
255
256         s = session_new(m, u, id);
257         if (!s)
258                 return -ENOMEM;
259
260         if (_session)
261                 *_session = s;
262
263         return 0;
264 }
265
266 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
267         User *u;
268
269         assert(m);
270         assert(name);
271
272         u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
273         if (u) {
274                 if (_user)
275                         *_user = u;
276
277                 return 0;
278         }
279
280         u = user_new(m, uid, gid, name);
281         if (!u)
282                 return -ENOMEM;
283
284         if (_user)
285                 *_user = u;
286
287         return 0;
288 }
289
290 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
291         uid_t uid;
292         gid_t gid;
293         int r;
294
295         assert(m);
296         assert(name);
297
298         r = get_user_creds(&name, &uid, &gid, NULL, NULL);
299         if (r < 0)
300                 return r;
301
302         return manager_add_user(m, uid, gid, name, _user);
303 }
304
305 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
306         struct passwd *p;
307
308         assert(m);
309
310         errno = 0;
311         p = getpwuid(uid);
312         if (!p)
313                 return errno ? -errno : -ENOENT;
314
315         return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
316 }
317
318 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
319         Inhibitor *i;
320
321         assert(m);
322         assert(id);
323
324         i = hashmap_get(m->inhibitors, id);
325         if (i) {
326                 if (_inhibitor)
327                         *_inhibitor = i;
328
329                 return 0;
330         }
331
332         i = inhibitor_new(m, id);
333         if (!i)
334                 return -ENOMEM;
335
336         if (_inhibitor)
337                 *_inhibitor = i;
338
339         return 0;
340 }
341
342 int manager_add_button(Manager *m, const char *name, Button **_button) {
343         Button *b;
344
345         assert(m);
346         assert(name);
347
348         b = hashmap_get(m->buttons, name);
349         if (b) {
350                 if (_button)
351                         *_button = b;
352
353                 return 0;
354         }
355
356         b = button_new(m, name);
357         if (!b)
358                 return -ENOMEM;
359
360         if (_button)
361                 *_button = b;
362
363         return 0;
364 }
365
366 int manager_process_seat_device(Manager *m, struct udev_device *d) {
367         Device *device;
368         int r;
369
370         assert(m);
371
372         if (streq_ptr(udev_device_get_action(d), "remove")) {
373
374                 device = hashmap_get(m->devices, udev_device_get_syspath(d));
375                 if (!device)
376                         return 0;
377
378                 seat_add_to_gc_queue(device->seat);
379                 device_free(device);
380
381         } else {
382                 const char *sn;
383                 Seat *seat;
384
385                 sn = udev_device_get_property_value(d, "ID_SEAT");
386                 if (isempty(sn))
387                         sn = "seat0";
388
389                 if (!seat_name_is_valid(sn)) {
390                         log_warning("Device with invalid seat name %s found, ignoring.", sn);
391                         return 0;
392                 }
393
394                 r = manager_add_device(m, udev_device_get_syspath(d), &device);
395                 if (r < 0)
396                         return r;
397
398                 r = manager_add_seat(m, sn, &seat);
399                 if (r < 0) {
400                         if (!device->seat)
401                                 device_free(device);
402
403                         return r;
404                 }
405
406                 device_attach(device, seat);
407                 seat_start(seat);
408         }
409
410         return 0;
411 }
412
413 int manager_process_button_device(Manager *m, struct udev_device *d) {
414         Button *b;
415
416         int r;
417
418         assert(m);
419
420         if (streq_ptr(udev_device_get_action(d), "remove")) {
421
422                 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
423                 if (!b)
424                         return 0;
425
426                 button_free(b);
427
428         } else {
429                 const char *sn;
430
431                 r = manager_add_button(m, udev_device_get_sysname(d), &b);
432                 if (r < 0)
433                         return r;
434
435                 sn = udev_device_get_property_value(d, "ID_SEAT");
436                 if (isempty(sn))
437                         sn = "seat0";
438
439                 button_set_seat(b, sn);
440                 button_open(b);
441         }
442
443         return 0;
444 }
445
446 int manager_enumerate_devices(Manager *m) {
447         struct udev_list_entry *item = NULL, *first = NULL;
448         struct udev_enumerate *e;
449         int r;
450
451         assert(m);
452
453         /* Loads devices from udev and creates seats for them as
454          * necessary */
455
456         e = udev_enumerate_new(m->udev);
457         if (!e) {
458                 r = -ENOMEM;
459                 goto finish;
460         }
461
462         r = udev_enumerate_add_match_subsystem(e, "graphics");
463         if (r < 0)
464                 goto finish;
465
466         r = udev_enumerate_add_match_tag(e, "seat");
467         if (r < 0)
468                 goto finish;
469
470         r = udev_enumerate_scan_devices(e);
471         if (r < 0)
472                 goto finish;
473
474         first = udev_enumerate_get_list_entry(e);
475         udev_list_entry_foreach(item, first) {
476                 struct udev_device *d;
477                 int k;
478
479                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
480                 if (!d) {
481                         r = -ENOMEM;
482                         goto finish;
483                 }
484
485                 k = manager_process_seat_device(m, d);
486                 udev_device_unref(d);
487
488                 if (k < 0)
489                         r = k;
490         }
491
492 finish:
493         if (e)
494                 udev_enumerate_unref(e);
495
496         return r;
497 }
498
499 int manager_enumerate_buttons(Manager *m) {
500         struct udev_list_entry *item = NULL, *first = NULL;
501         struct udev_enumerate *e;
502         int r;
503
504         assert(m);
505
506         /* Loads buttons from udev */
507
508         if (m->handle_power_key == HANDLE_IGNORE &&
509             m->handle_suspend_key == HANDLE_IGNORE &&
510             m->handle_hibernate_key == HANDLE_IGNORE &&
511             m->handle_lid_switch == HANDLE_IGNORE)
512                 return 0;
513
514         e = udev_enumerate_new(m->udev);
515         if (!e) {
516                 r = -ENOMEM;
517                 goto finish;
518         }
519
520         r = udev_enumerate_add_match_subsystem(e, "input");
521         if (r < 0)
522                 goto finish;
523
524         r = udev_enumerate_add_match_tag(e, "power-switch");
525         if (r < 0)
526                 goto finish;
527
528         r = udev_enumerate_scan_devices(e);
529         if (r < 0)
530                 goto finish;
531
532         first = udev_enumerate_get_list_entry(e);
533         udev_list_entry_foreach(item, first) {
534                 struct udev_device *d;
535                 int k;
536
537                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
538                 if (!d) {
539                         r = -ENOMEM;
540                         goto finish;
541                 }
542
543                 k = manager_process_button_device(m, d);
544                 udev_device_unref(d);
545
546                 if (k < 0)
547                         r = k;
548         }
549
550 finish:
551         if (e)
552                 udev_enumerate_unref(e);
553
554         return r;
555 }
556
557 int manager_enumerate_seats(Manager *m) {
558         DIR *d;
559         struct dirent *de;
560         int r = 0;
561
562         assert(m);
563
564         /* This loads data about seats stored on disk, but does not
565          * actually create any seats. Removes data of seats that no
566          * longer exist. */
567
568         d = opendir("/run/systemd/seats");
569         if (!d) {
570                 if (errno == ENOENT)
571                         return 0;
572
573                 log_error("Failed to open /run/systemd/seats: %m");
574                 return -errno;
575         }
576
577         while ((de = readdir(d))) {
578                 Seat *s;
579                 int k;
580
581                 if (!dirent_is_file(de))
582                         continue;
583
584                 s = hashmap_get(m->seats, de->d_name);
585                 if (!s) {
586                         unlinkat(dirfd(d), de->d_name, 0);
587                         continue;
588                 }
589
590                 k = seat_load(s);
591                 if (k < 0)
592                         r = k;
593         }
594
595         closedir(d);
596
597         return r;
598 }
599
600 static int manager_enumerate_users_from_cgroup(Manager *m) {
601         int r = 0, k;
602         char *name;
603         DIR *d;
604
605         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
606         if (r < 0) {
607                 if (r == -ENOENT)
608                         return 0;
609
610                 log_error("Failed to open %s: %s", m->cgroup_path, strerror(-r));
611                 return r;
612         }
613
614         while ((k = cg_read_subgroup(d, &name)) > 0) {
615                 User *user;
616
617                 k = manager_add_user_by_name(m, name, &user);
618                 if (k < 0) {
619                         free(name);
620                         r = k;
621                         continue;
622                 }
623
624                 user_add_to_gc_queue(user);
625
626                 if (!user->cgroup_path)
627                         if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) {
628                                 r = -ENOMEM;
629                                 free(name);
630                                 break;
631                         }
632
633                 free(name);
634         }
635
636         if (r >= 0 && k < 0)
637                 r = k;
638
639         closedir(d);
640
641         return r;
642 }
643
644 static int manager_enumerate_linger_users(Manager *m) {
645         DIR *d;
646         struct dirent *de;
647         int r = 0;
648
649         d = opendir("/var/lib/systemd/linger");
650         if (!d) {
651                 if (errno == ENOENT)
652                         return 0;
653
654                 log_error("Failed to open /var/lib/systemd/linger/: %m");
655                 return -errno;
656         }
657
658         while ((de = readdir(d))) {
659                 int k;
660
661                 if (!dirent_is_file(de))
662                         continue;
663
664                 k = manager_add_user_by_name(m, de->d_name, NULL);
665                 if (k < 0) {
666                         log_notice("Couldn't add lingering user %s: %s", de->d_name, strerror(-k));
667                         r = k;
668                 }
669         }
670
671         closedir(d);
672
673         return r;
674 }
675
676 int manager_enumerate_users(Manager *m) {
677         DIR *d;
678         struct dirent *de;
679         int r, k;
680
681         assert(m);
682
683         /* First, enumerate user cgroups */
684         r = manager_enumerate_users_from_cgroup(m);
685
686         /* Second, add lingering users on top */
687         k = manager_enumerate_linger_users(m);
688         if (k < 0)
689                 r = k;
690
691         /* Third, read in user data stored on disk */
692         d = opendir("/run/systemd/users");
693         if (!d) {
694                 if (errno == ENOENT)
695                         return 0;
696
697                 log_error("Failed to open /run/systemd/users: %m");
698                 return -errno;
699         }
700
701         while ((de = readdir(d))) {
702                 uid_t uid;
703                 User *u;
704
705                 if (!dirent_is_file(de))
706                         continue;
707
708                 k = parse_uid(de->d_name, &uid);
709                 if (k < 0) {
710                         log_error("Failed to parse file name %s: %s", de->d_name, strerror(-k));
711                         continue;
712                 }
713
714                 u = hashmap_get(m->users, ULONG_TO_PTR(uid));
715                 if (!u) {
716                         unlinkat(dirfd(d), de->d_name, 0);
717                         continue;
718                 }
719
720                 k = user_load(u);
721                 if (k < 0)
722                         r = k;
723         }
724
725         closedir(d);
726
727         return r;
728 }
729
730 static int manager_enumerate_sessions_from_cgroup(Manager *m) {
731         User *u;
732         Iterator i;
733         int r = 0;
734
735         HASHMAP_FOREACH(u, m->users, i) {
736                 DIR *d;
737                 char *name;
738                 int k;
739
740                 if (!u->cgroup_path)
741                         continue;
742
743                 k = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &d);
744                 if (k < 0) {
745                         if (k == -ENOENT)
746                                 continue;
747
748                         log_error("Failed to open %s: %s", u->cgroup_path, strerror(-k));
749                         r = k;
750                         continue;
751                 }
752
753                 while ((k = cg_read_subgroup(d, &name)) > 0) {
754                         Session *session;
755
756                         if (streq(name, "shared"))
757                                 continue;
758
759                         k = manager_add_session(m, u, name, &session);
760                         if (k < 0) {
761                                 free(name);
762                                 break;
763                         }
764
765                         session_add_to_gc_queue(session);
766
767                         if (!session->cgroup_path)
768                                 if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) {
769                                         k = -ENOMEM;
770                                         free(name);
771                                         break;
772                                 }
773
774                         free(name);
775                 }
776
777                 closedir(d);
778
779                 if (k < 0)
780                         r = k;
781         }
782
783         return r;
784 }
785
786 int manager_enumerate_sessions(Manager *m) {
787         DIR *d;
788         struct dirent *de;
789         int r = 0;
790
791         assert(m);
792
793         /* First enumerate session cgroups */
794         r = manager_enumerate_sessions_from_cgroup(m);
795
796         /* Second, read in session data stored on disk */
797         d = opendir("/run/systemd/sessions");
798         if (!d) {
799                 if (errno == ENOENT)
800                         return 0;
801
802                 log_error("Failed to open /run/systemd/sessions: %m");
803                 return -errno;
804         }
805
806         while ((de = readdir(d))) {
807                 struct Session *s;
808                 int k;
809
810                 if (!dirent_is_file(de))
811                         continue;
812
813                 s = hashmap_get(m->sessions, de->d_name);
814                 if (!s) {
815                         unlinkat(dirfd(d), de->d_name, 0);
816                         continue;
817                 }
818
819                 k = session_load(s);
820                 if (k < 0)
821                         r = k;
822         }
823
824         closedir(d);
825
826         return r;
827 }
828
829 int manager_enumerate_inhibitors(Manager *m) {
830         DIR *d;
831         struct dirent *de;
832         int r = 0;
833
834         assert(m);
835
836         d = opendir("/run/systemd/inhibit");
837         if (!d) {
838                 if (errno == ENOENT)
839                         return 0;
840
841                 log_error("Failed to open /run/systemd/inhibit: %m");
842                 return -errno;
843         }
844
845         while ((de = readdir(d))) {
846                 int k;
847                 Inhibitor *i;
848
849                 if (!dirent_is_file(de))
850                         continue;
851
852                 k = manager_add_inhibitor(m, de->d_name, &i);
853                 if (k < 0) {
854                         log_notice("Couldn't add inhibitor %s: %s", de->d_name, strerror(-k));
855                         r = k;
856                         continue;
857                 }
858
859                 k = inhibitor_load(i);
860                 if (k < 0)
861                         r = k;
862         }
863
864         closedir(d);
865
866         return r;
867 }
868
869 int manager_dispatch_seat_udev(Manager *m) {
870         struct udev_device *d;
871         int r;
872
873         assert(m);
874
875         d = udev_monitor_receive_device(m->udev_seat_monitor);
876         if (!d)
877                 return -ENOMEM;
878
879         r = manager_process_seat_device(m, d);
880         udev_device_unref(d);
881
882         return r;
883 }
884
885 int manager_dispatch_vcsa_udev(Manager *m) {
886         struct udev_device *d;
887         int r = 0;
888         const char *name;
889
890         assert(m);
891
892         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
893         if (!d)
894                 return -ENOMEM;
895
896         name = udev_device_get_sysname(d);
897
898         /* Whenever a VCSA device is removed try to reallocate our
899          * VTs, to make sure our auto VTs never go away. */
900
901         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
902                 r = seat_preallocate_vts(m->vtconsole);
903
904         udev_device_unref(d);
905
906         return r;
907 }
908
909 int manager_dispatch_button_udev(Manager *m) {
910         struct udev_device *d;
911         int r;
912
913         assert(m);
914
915         d = udev_monitor_receive_device(m->udev_button_monitor);
916         if (!d)
917                 return -ENOMEM;
918
919         r = manager_process_button_device(m, d);
920         udev_device_unref(d);
921
922         return r;
923 }
924
925 int manager_dispatch_console(Manager *m) {
926         assert(m);
927
928         if (m->vtconsole)
929                 seat_read_active_vt(m->vtconsole);
930
931         return 0;
932 }
933
934 static int vt_is_busy(int vtnr) {
935         struct vt_stat vt_stat;
936         int r = 0, fd;
937
938         assert(vtnr >= 1);
939
940         /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
941          * we'd open the latter we'd open the foreground tty which
942          * hence would be unconditionally busy. By opening /dev/tty1
943          * we avoid this. Since tty1 is special and needs to be an
944          * explicitly loaded getty or DM this is safe. */
945
946         fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
947         if (fd < 0)
948                 return -errno;
949
950         if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
951                 r = -errno;
952         else
953                 r = !!(vt_stat.v_state & (1 << vtnr));
954
955         close_nointr_nofail(fd);
956
957         return r;
958 }
959
960 int manager_spawn_autovt(Manager *m, int vtnr) {
961         int r;
962         char *name = NULL;
963         const char *mode = "fail";
964
965         assert(m);
966         assert(vtnr >= 1);
967
968         if ((unsigned) vtnr > m->n_autovts &&
969             (unsigned) vtnr != m->reserve_vt)
970                 return 0;
971
972         if ((unsigned) vtnr != m->reserve_vt) {
973                 /* If this is the reserved TTY, we'll start the getty
974                  * on it in any case, but otherwise only if it is not
975                  * busy. */
976
977                 r = vt_is_busy(vtnr);
978                 if (r < 0)
979                         return r;
980                 else if (r > 0)
981                         return -EBUSY;
982         }
983
984         if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
985                 log_error("Could not allocate service name.");
986                 r = -ENOMEM;
987                 goto finish;
988         }
989
990         r = bus_method_call_with_reply (
991                         m->bus,
992                         "org.freedesktop.systemd1",
993                         "/org/freedesktop/systemd1",
994                         "org.freedesktop.systemd1.Manager",
995                         "StartUnit",
996                         NULL,
997                         NULL,
998                         DBUS_TYPE_STRING, &name,
999                         DBUS_TYPE_STRING, &mode,
1000                         DBUS_TYPE_INVALID);
1001
1002 finish:
1003         free(name);
1004
1005         return r;
1006 }
1007
1008 static int manager_reserve_vt(Manager *m) {
1009         _cleanup_free_ char *p = NULL;
1010
1011         assert(m);
1012
1013         if (m->reserve_vt <= 0)
1014                 return 0;
1015
1016         if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
1017                 return log_oom();
1018
1019         m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
1020         if (m->reserve_vt_fd < 0) {
1021
1022                 /* Don't complain on VT-less systems */
1023                 if (errno != ENOENT)
1024                         log_warning("Failed to pin reserved VT: %m");
1025                 return -errno;
1026         }
1027
1028         return 0;
1029 }
1030
1031 int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
1032         Session *s;
1033         char *p;
1034
1035         assert(m);
1036         assert(cgroup);
1037         assert(session);
1038
1039         s = hashmap_get(m->session_cgroups, cgroup);
1040         if (s) {
1041                 *session = s;
1042                 return 1;
1043         }
1044
1045         p = strdup(cgroup);
1046         if (!p)
1047                 return log_oom();
1048
1049         for (;;) {
1050                 char *e;
1051
1052                 e = strrchr(p, '/');
1053                 if (!e || e == p) {
1054                         free(p);
1055                         *session = NULL;
1056                         return 0;
1057                 }
1058
1059                 *e = 0;
1060
1061                 s = hashmap_get(m->session_cgroups, p);
1062                 if (s) {
1063                         free(p);
1064                         *session = s;
1065                         return 1;
1066                 }
1067         }
1068 }
1069
1070 int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) {
1071         User *u;
1072         char *p;
1073
1074         assert(m);
1075         assert(cgroup);
1076         assert(user);
1077
1078         u = hashmap_get(m->user_cgroups, cgroup);
1079         if (u) {
1080                 *user = u;
1081                 return 1;
1082         }
1083
1084         p = strdup(cgroup);
1085         if (!p)
1086                 return log_oom();
1087
1088         for (;;) {
1089                 char *e;
1090
1091                 e = strrchr(p, '/');
1092                 if (!e || e == p) {
1093                         free(p);
1094                         *user = NULL;
1095                         return 0;
1096                 }
1097
1098                 *e = 0;
1099
1100                 u = hashmap_get(m->user_cgroups, p);
1101                 if (u) {
1102                         free(p);
1103                         *user = u;
1104                         return 1;
1105                 }
1106         }
1107 }
1108
1109 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
1110         char *p;
1111         int r;
1112
1113         assert(m);
1114         assert(pid >= 1);
1115         assert(session);
1116
1117         r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p);
1118         if (r < 0)
1119                 return r;
1120
1121         r = manager_get_session_by_cgroup(m, p, session);
1122         free(p);
1123
1124         return r;
1125 }
1126
1127 void manager_cgroup_notify_empty(Manager *m, const char *cgroup) {
1128         Session *s;
1129         User *u;
1130         int r;
1131
1132         r = manager_get_session_by_cgroup(m, cgroup, &s);
1133         if (r > 0)
1134                 session_add_to_gc_queue(s);
1135
1136         r = manager_get_user_by_cgroup(m, cgroup, &u);
1137         if (r > 0)
1138                 user_add_to_gc_queue(u);
1139 }
1140
1141 static void manager_dispatch_other(Manager *m, int fd) {
1142         Session *s;
1143         Inhibitor *i;
1144         Button *b;
1145
1146         assert_se(m);
1147         assert_se(fd >= 0);
1148
1149         s = hashmap_get(m->session_fds, INT_TO_PTR(fd + 1));
1150         if (s) {
1151                 assert(s->fifo_fd == fd);
1152                 session_remove_fifo(s);
1153                 session_stop(s);
1154                 return;
1155         }
1156
1157         i = hashmap_get(m->inhibitor_fds, INT_TO_PTR(fd + 1));
1158         if (i) {
1159                 assert(i->fifo_fd == fd);
1160                 inhibitor_stop(i);
1161                 inhibitor_free(i);
1162                 return;
1163         }
1164
1165         b = hashmap_get(m->button_fds, INT_TO_PTR(fd + 1));
1166         if (b) {
1167                 assert(b->fd == fd);
1168                 button_process(b);
1169                 return;
1170         }
1171
1172         assert_not_reached("Got event for unknown fd");
1173 }
1174
1175 static int manager_connect_bus(Manager *m) {
1176         DBusError error;
1177         int r;
1178         struct epoll_event ev;
1179
1180         assert(m);
1181         assert(!m->bus);
1182         assert(m->bus_fd < 0);
1183
1184         dbus_error_init(&error);
1185
1186         m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
1187         if (!m->bus) {
1188                 log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
1189                 r = -ECONNREFUSED;
1190                 goto fail;
1191         }
1192
1193         if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/login1", &bus_manager_vtable, m) ||
1194             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/seat", &bus_seat_vtable, m) ||
1195             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/session", &bus_session_vtable, m) ||
1196             !dbus_connection_register_fallback(m->bus, "/org/freedesktop/login1/user", &bus_user_vtable, m) ||
1197             !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
1198                 r = log_oom();
1199                 goto fail;
1200         }
1201
1202         dbus_bus_add_match(m->bus,
1203                            "type='signal',"
1204                            "interface='org.freedesktop.systemd1.Agent',"
1205                            "member='Released',"
1206                            "path='/org/freedesktop/systemd1/agent'",
1207                            &error);
1208
1209         if (dbus_error_is_set(&error)) {
1210                 log_error("Failed to register match: %s", bus_error_message(&error));
1211                 r = -EIO;
1212                 goto fail;
1213         }
1214
1215         r = dbus_bus_request_name(m->bus, "org.freedesktop.login1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
1216         if (dbus_error_is_set(&error)) {
1217                 log_error("Failed to register name on bus: %s", bus_error_message(&error));
1218                 r = -EIO;
1219                 goto fail;
1220         }
1221
1222         if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {
1223                 log_error("Failed to acquire name.");
1224                 r = -EEXIST;
1225                 goto fail;
1226         }
1227
1228         m->bus_fd = bus_loop_open(m->bus);
1229         if (m->bus_fd < 0) {
1230                 r = m->bus_fd;
1231                 goto fail;
1232         }
1233
1234         zero(ev);
1235         ev.events = EPOLLIN;
1236         ev.data.u32 = FD_BUS;
1237
1238         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
1239                 goto fail;
1240
1241         return 0;
1242
1243 fail:
1244         dbus_error_free(&error);
1245
1246         return r;
1247 }
1248
1249 static int manager_connect_console(Manager *m) {
1250         struct epoll_event ev;
1251
1252         assert(m);
1253         assert(m->console_active_fd < 0);
1254
1255         /* On certain architectures (S390 and Xen, and containers),
1256            /dev/tty0 does not exist, so don't fail if we can't open
1257            it. */
1258         if (access("/dev/tty0", F_OK) < 0) {
1259                 m->console_active_fd = -1;
1260                 return 0;
1261         }
1262
1263         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
1264         if (m->console_active_fd < 0) {
1265
1266                 /* On some systems the device node /dev/tty0 may exist
1267                  * even though /sys/class/tty/tty0 does not. */
1268                 if (errno == ENOENT)
1269                         return 0;
1270
1271                 log_error("Failed to open /sys/class/tty/tty0/active: %m");
1272                 return -errno;
1273         }
1274
1275         zero(ev);
1276         ev.events = 0;
1277         ev.data.u32 = FD_CONSOLE;
1278
1279         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0)
1280                 return -errno;
1281
1282         return 0;
1283 }
1284
1285 static int manager_connect_udev(Manager *m) {
1286         struct epoll_event ev;
1287         int r;
1288
1289         assert(m);
1290         assert(!m->udev_seat_monitor);
1291         assert(!m->udev_vcsa_monitor);
1292         assert(!m->udev_button_monitor);
1293
1294         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1295         if (!m->udev_seat_monitor)
1296                 return -ENOMEM;
1297
1298         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat");
1299         if (r < 0)
1300                 return r;
1301
1302         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_seat_monitor, "graphics", NULL);
1303         if (r < 0)
1304                 return r;
1305
1306         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
1307         if (r < 0)
1308                 return r;
1309
1310         m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor);
1311
1312         zero(ev);
1313         ev.events = EPOLLIN;
1314         ev.data.u32 = FD_SEAT_UDEV;
1315         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0)
1316                 return -errno;
1317
1318         /* Don't watch keys if nobody cares */
1319         if (m->handle_power_key != HANDLE_IGNORE ||
1320             m->handle_suspend_key != HANDLE_IGNORE ||
1321             m->handle_hibernate_key != HANDLE_IGNORE ||
1322             m->handle_lid_switch != HANDLE_IGNORE) {
1323
1324                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1325                 if (!m->udev_button_monitor)
1326                         return -ENOMEM;
1327
1328                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
1329                 if (r < 0)
1330                         return r;
1331
1332                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
1333                 if (r < 0)
1334                         return r;
1335
1336                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
1337                 if (r < 0)
1338                         return r;
1339
1340                 m->udev_button_fd = udev_monitor_get_fd(m->udev_button_monitor);
1341
1342                 zero(ev);
1343                 ev.events = EPOLLIN;
1344                 ev.data.u32 = FD_BUTTON_UDEV;
1345                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_button_fd, &ev) < 0)
1346                         return -errno;
1347         }
1348
1349         /* Don't bother watching VCSA devices, if nobody cares */
1350         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1351
1352                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1353                 if (!m->udev_vcsa_monitor)
1354                         return -ENOMEM;
1355
1356                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1357                 if (r < 0)
1358                         return r;
1359
1360                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1361                 if (r < 0)
1362                         return r;
1363
1364                 m->udev_vcsa_fd = udev_monitor_get_fd(m->udev_vcsa_monitor);
1365
1366                 zero(ev);
1367                 ev.events = EPOLLIN;
1368                 ev.data.u32 = FD_VCSA_UDEV;
1369                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_vcsa_fd, &ev) < 0)
1370                         return -errno;
1371         }
1372
1373         return 0;
1374 }
1375
1376 void manager_gc(Manager *m, bool drop_not_started) {
1377         Seat *seat;
1378         Session *session;
1379         User *user;
1380
1381         assert(m);
1382
1383         while ((seat = m->seat_gc_queue)) {
1384                 LIST_REMOVE(Seat, gc_queue, m->seat_gc_queue, seat);
1385                 seat->in_gc_queue = false;
1386
1387                 if (seat_check_gc(seat, drop_not_started) == 0) {
1388                         seat_stop(seat);
1389                         seat_free(seat);
1390                 }
1391         }
1392
1393         while ((session = m->session_gc_queue)) {
1394                 LIST_REMOVE(Session, gc_queue, m->session_gc_queue, session);
1395                 session->in_gc_queue = false;
1396
1397                 if (session_check_gc(session, drop_not_started) == 0) {
1398                         session_stop(session);
1399                         session_free(session);
1400                 }
1401         }
1402
1403         while ((user = m->user_gc_queue)) {
1404                 LIST_REMOVE(User, gc_queue, m->user_gc_queue, user);
1405                 user->in_gc_queue = false;
1406
1407                 if (user_check_gc(user, drop_not_started) == 0) {
1408                         user_stop(user);
1409                         user_free(user);
1410                 }
1411         }
1412 }
1413
1414 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
1415         Session *s;
1416         bool idle_hint;
1417         dual_timestamp ts = { 0, 0 };
1418         Iterator i;
1419
1420         assert(m);
1421
1422         idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
1423
1424         HASHMAP_FOREACH(s, m->sessions, i) {
1425                 dual_timestamp k;
1426                 int ih;
1427
1428                 ih = session_get_idle_hint(s, &k);
1429                 if (ih < 0)
1430                         return ih;
1431
1432                 if (!ih) {
1433                         if (!idle_hint) {
1434                                 if (k.monotonic < ts.monotonic)
1435                                         ts = k;
1436                         } else {
1437                                 idle_hint = false;
1438                                 ts = k;
1439                         }
1440                 } else if (idle_hint) {
1441
1442                         if (k.monotonic > ts.monotonic)
1443                                 ts = k;
1444                 }
1445         }
1446
1447         if (t)
1448                 *t = ts;
1449
1450         return idle_hint;
1451 }
1452
1453 int manager_dispatch_idle_action(Manager *m) {
1454         struct dual_timestamp since;
1455         struct itimerspec its;
1456         int r;
1457         usec_t n;
1458
1459         assert(m);
1460
1461         if (m->idle_action == HANDLE_IGNORE ||
1462             m->idle_action_usec <= 0) {
1463                 r = 0;
1464                 goto finish;
1465         }
1466
1467         zero(its);
1468         n = now(CLOCK_MONOTONIC);
1469
1470         r = manager_get_idle_hint(m, &since);
1471         if (r <= 0)
1472                 /* Not idle. Let's check if after a timeout it it might be idle then. */
1473                 timespec_store(&its.it_value, n + m->idle_action_usec);
1474         else {
1475                 /* Idle! Let's see if it's time to do something, or if
1476                  * we shall sleep for longer. */
1477
1478                 if (n >= since.monotonic + m->idle_action_usec &&
1479                     (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1480                         log_info("System idle. Taking action.");
1481
1482                         manager_handle_action(m, 0, m->idle_action, false, false);
1483                         m->idle_action_not_before_usec = n;
1484                 }
1485
1486                 timespec_store(&its.it_value, MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec);
1487         }
1488
1489         if (m->idle_action_fd < 0) {
1490                 struct epoll_event ev;
1491
1492                 m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
1493                 if (m->idle_action_fd < 0) {
1494                         log_error("Failed to create idle action timer: %m");
1495                         r = -errno;
1496                         goto finish;
1497                 }
1498
1499                 zero(ev);
1500                 ev.events = EPOLLIN;
1501                 ev.data.u32 = FD_IDLE_ACTION;
1502
1503                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) {
1504                         log_error("Failed to add idle action timer to epoll: %m");
1505                         r = -errno;
1506                         goto finish;
1507                 }
1508         }
1509
1510         if (timerfd_settime(m->idle_action_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) {
1511                 log_error("Failed to reset timerfd: %m");
1512                 r = -errno;
1513                 goto finish;
1514         }
1515
1516         return 0;
1517
1518 finish:
1519         if (m->idle_action_fd >= 0) {
1520                 close_nointr_nofail(m->idle_action_fd);
1521                 m->idle_action_fd = -1;
1522         }
1523
1524         return r;
1525 }
1526 int manager_startup(Manager *m) {
1527         int r;
1528         Seat *seat;
1529         Session *session;
1530         User *user;
1531         Inhibitor *inhibitor;
1532         Iterator i;
1533
1534         assert(m);
1535         assert(m->epoll_fd <= 0);
1536
1537         cg_shorten_controllers(m->reset_controllers);
1538         cg_shorten_controllers(m->controllers);
1539
1540         m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1541         if (m->epoll_fd < 0)
1542                 return -errno;
1543
1544         /* Connect to console */
1545         r = manager_connect_console(m);
1546         if (r < 0)
1547                 return r;
1548
1549         /* Connect to udev */
1550         r = manager_connect_udev(m);
1551         if (r < 0)
1552                 return r;
1553
1554         /* Connect to the bus */
1555         r = manager_connect_bus(m);
1556         if (r < 0)
1557                 return r;
1558
1559         /* Instantiate magic seat 0 */
1560         r = manager_add_seat(m, "seat0", &m->vtconsole);
1561         if (r < 0)
1562                 return r;
1563
1564         /* Deserialize state */
1565         manager_enumerate_devices(m);
1566         manager_enumerate_seats(m);
1567         manager_enumerate_users(m);
1568         manager_enumerate_sessions(m);
1569         manager_enumerate_inhibitors(m);
1570         manager_enumerate_buttons(m);
1571
1572         /* Remove stale objects before we start them */
1573         manager_gc(m, false);
1574
1575         /* Reserve the special reserved VT */
1576         manager_reserve_vt(m);
1577
1578         /* And start everything */
1579         HASHMAP_FOREACH(seat, m->seats, i)
1580                 seat_start(seat);
1581
1582         HASHMAP_FOREACH(user, m->users, i)
1583                 user_start(user);
1584
1585         HASHMAP_FOREACH(session, m->sessions, i)
1586                 session_start(session);
1587
1588         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1589                 inhibitor_start(inhibitor);
1590
1591         manager_dispatch_idle_action(m);
1592
1593         return 0;
1594 }
1595
1596 static int manager_recheck_buttons(Manager *m) {
1597         Iterator i;
1598         Button *b;
1599         int r = 0;
1600
1601         assert(m);
1602
1603         HASHMAP_FOREACH(b, m->buttons, i) {
1604                 int q;
1605
1606                 q = button_recheck(b);
1607                 if (q > 0)
1608                         return 1;
1609                 if (q < 0)
1610                         r = q;
1611         }
1612
1613         return r;
1614 }
1615
1616 int manager_run(Manager *m) {
1617         assert(m);
1618
1619         for (;;) {
1620                 struct epoll_event event;
1621                 int n;
1622                 int msec = -1;
1623
1624                 manager_gc(m, true);
1625
1626                 if (manager_dispatch_delayed(m) > 0)
1627                         continue;
1628
1629                 if (manager_recheck_buttons(m) > 0)
1630                         continue;
1631
1632                 if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
1633                         continue;
1634
1635                 manager_gc(m, true);
1636
1637                 if (m->delayed_unit) {
1638                         usec_t x, y;
1639
1640                         x = now(CLOCK_MONOTONIC);
1641                         y = m->delayed_timestamp + m->inhibit_delay_max;
1642
1643                         msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC);
1644                 }
1645
1646                 n = epoll_wait(m->epoll_fd, &event, 1, msec);
1647                 if (n < 0) {
1648                         if (errno == EINTR || errno == EAGAIN)
1649                                 continue;
1650
1651                         log_error("epoll() failed: %m");
1652                         return -errno;
1653                 }
1654
1655                 if (n == 0)
1656                         continue;
1657
1658                 switch (event.data.u32) {
1659
1660                 case FD_SEAT_UDEV:
1661                         manager_dispatch_seat_udev(m);
1662                         break;
1663
1664                 case FD_VCSA_UDEV:
1665                         manager_dispatch_vcsa_udev(m);
1666                         break;
1667
1668                 case FD_BUTTON_UDEV:
1669                         manager_dispatch_button_udev(m);
1670                         break;
1671
1672                 case FD_CONSOLE:
1673                         manager_dispatch_console(m);
1674                         break;
1675
1676                 case FD_IDLE_ACTION:
1677                         manager_dispatch_idle_action(m);
1678                         break;
1679
1680                 case FD_BUS:
1681                         bus_loop_dispatch(m->bus_fd);
1682                         break;
1683
1684                 default:
1685                         if (event.data.u32 >= FD_OTHER_BASE)
1686                                 manager_dispatch_other(m, event.data.u32 - FD_OTHER_BASE);
1687                 }
1688         }
1689
1690         return 0;
1691 }
1692
1693 static int manager_parse_config_file(Manager *m) {
1694         FILE *f;
1695         const char *fn;
1696         int r;
1697
1698         assert(m);
1699
1700         fn = "/etc/systemd/logind.conf";
1701         f = fopen(fn, "re");
1702         if (!f) {
1703                 if (errno == ENOENT)
1704                         return 0;
1705
1706                 log_warning("Failed to open configuration file %s: %m", fn);
1707                 return -errno;
1708         }
1709
1710         r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m);
1711         if (r < 0)
1712                 log_warning("Failed to parse configuration file: %s", strerror(-r));
1713
1714         fclose(f);
1715
1716         return r;
1717 }
1718
1719 int main(int argc, char *argv[]) {
1720         Manager *m = NULL;
1721         int r;
1722
1723         log_set_target(LOG_TARGET_AUTO);
1724         log_set_facility(LOG_AUTH);
1725         log_parse_environment();
1726         log_open();
1727
1728         umask(0022);
1729
1730         if (argc != 1) {
1731                 log_error("This program takes no arguments.");
1732                 r = -EINVAL;
1733                 goto finish;
1734         }
1735
1736         m = manager_new();
1737         if (!m) {
1738                 r = log_oom();
1739                 goto finish;
1740         }
1741
1742         manager_parse_config_file(m);
1743
1744         r = manager_startup(m);
1745         if (r < 0) {
1746                 log_error("Failed to fully start up daemon: %s", strerror(-r));
1747                 goto finish;
1748         }
1749
1750         log_debug("systemd-logind running as pid %lu", (unsigned long) getpid());
1751
1752         sd_notify(false,
1753                   "READY=1\n"
1754                   "STATUS=Processing requests...");
1755
1756         r = manager_run(m);
1757
1758         log_debug("systemd-logind stopped as pid %lu", (unsigned long) getpid());
1759
1760 finish:
1761         sd_notify(false,
1762                   "STATUS=Shutting down...");
1763
1764         if (m)
1765                 manager_free(m);
1766
1767         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1768 }